home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / IPFlakeWay / Squelch Module / source / ProxyModule.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  96.8 KB  |  3,399 lines

  1. // =================================================================================
  2. //    ProxyModule.c                ©1996-1999 Sustainable Softworks All rights reserved.
  3. // =================================================================================
  4. //    DLPI STREAMS filter and TPI STREAMS Driver
  5. //
  6. //    This module is both a STREAMS module "Proxym" and STREAMS driver "Proxy".
  7. //
  8. //        The module is autopushed above a DLPI device (such as PPP) to monitor
  9. //        network traffic flowing to that device.
  10. //
  11. //        The module is opened as a driver to communicate monitored statistics
  12. //        to a network client above the stream head.
  13. //
  14. //    Currently, we just count data bytes flowing in each direction.
  15. //
  16. //    Original Version 8/2/96 by Peter Sichel
  17.  
  18. #if powerc
  19. #include "DCon.h"
  20. #endif
  21. #ifndef __OPENTPTMODULE__
  22. #include <OpenTptModule.h>
  23. #endif
  24. #ifndef _MPS_STROPTS_
  25. #include <stropts.h>
  26. #endif
  27. #ifndef _TIHDR_
  28. #include <tihdr.h>
  29. #endif
  30. #ifndef __DLPI__
  31. #include <dlpi.h>
  32. #endif
  33. #include <OpenTptLinks.h>
  34.  
  35. #include <OpenTptInternet.h>
  36. #include "ProxyModule.h"
  37. #include "NatProcess.h"
  38. #include "FilterTable.h"
  39.  
  40. #define nilp(type)        ((type*)0)
  41.  
  42. //--------------------------------------------------------------
  43. //    • Forward function declarations
  44. //--------------------------------------------------------------
  45. int        proxy_admin(void);
  46. int        proxy_close(queue_t*, int, cred_t*);
  47. int        proxy_open(queue_t*, dev_t*, int, int, cred_t*);
  48. int        proxy_rsrv(queue_t*);
  49. int        proxy_wsrv(queue_t*);
  50. int        proxy_rput(queue_t*, mblk_t*);
  51. int        proxy_wput(queue_t*, mblk_t*);
  52.  
  53. int        proxy_wproto(queue_t* wrq, mblk_t*);
  54. int        proxy_wdata(queue_t* wrq, mblk_t*);
  55. int        proxy_rproto(queue_t* rdq, mblk_t*);
  56. int        proxy_rdata(queue_t* rdq, mblk_t*);
  57.  
  58. int        proxym_close(queue_t*, int, cred_t*);
  59. int        proxym_open(queue_t*, dev_t*, int, int, cred_t*);
  60. int        proxym_rsrv(queue_t*);
  61. int        proxym_wsrv(queue_t*);
  62. int        proxym_rput(queue_t*, mblk_t*);
  63. int        proxym_wput(queue_t*, mblk_t*);
  64.  
  65. int        proxym_wproto(queue_t* wrq, mblk_t*);
  66. int        proxym_wdata(queue_t* wrq, mblk_t*);
  67. int        proxym_rproto(queue_t* rdq, mblk_t*);
  68. int        proxym_rdata(queue_t* rdq, mblk_t*);
  69.  
  70. int        proxy_error(queue_t* rdq, mblk_t*, int error);
  71. void     ReplyErrorAck(queue_t* rdq, mblk_t*, long reqType,
  72.                       int xtiErr, int macErr);
  73. mblk_t* ReuseMessage(mblk_t* mp, size_t size);
  74. SInt32    proxy_CountMessage(mblk_t* mp);
  75. UInt32    HashName(char* inName);
  76. void    proxy_GetTimedStat(queue_t* q, SInt32* outSequenceNumber, SInt32* outRCount, SInt32* outWCount);
  77. Boolean    proxy_SendStats(queue_t* q);
  78. Boolean proxy_SendNat(translationEntry_t table[], queue_t* q, UInt8 selector);
  79. Boolean proxy_SendFilters(queue_t* q);
  80.  
  81. mblk_t*    my_tpi_unitdata_ind(mblk_t* trailer_mp, char* src, size_t src_length,
  82.             char* opt, size_t opt_length);
  83. UInt8*    FindWDatagram(queue_t* q, mblk_t* mp, mblk_t** outMp, SInt32* dataOffset);
  84. UInt8*    FindRDatagram(queue_t* q, mblk_t* mp, mblk_t** outMp, SInt32* dataOffset);
  85. UInt8    FilterPacket(UInt8* datagram, mblk_t* mp, FilterEntry_t* filterData);
  86.  
  87. // ===========================================================================
  88.  
  89. #pragma mark • Shared Global Data •
  90.  
  91. //--------------------------------------------------------------
  92. // • Global Driver Variables
  93. //--------------------------------------------------------------
  94.  
  95. static char* gProxymListHead    = NULL;    // used for mi_open and mi_close support code
  96. static char* gProxyListHead        = NULL;
  97.  
  98. //    Statistics information
  99. struct proxy_stats
  100. {
  101.     SInt32    flags;
  102.     SInt32    rCount;
  103.     SInt32    wCount;
  104.     SInt32    filter1;
  105.     SInt32    filter2;
  106.     SInt32    filter3;
  107.     SInt32    filter4;
  108. };
  109. static struct proxy_stats mstat =
  110. {
  111.     0,            // flags
  112.     0,            // read data count
  113.     0,            // write data count
  114.     0,            // filter1 value
  115.     0,            // filter2 value
  116.     0,            // filter3 value
  117.     0            // filter4 value
  118. };
  119.  
  120. static Boolean    proxymRefCountAdjusted    = false;
  121. static Boolean    proxyRefCountAdjusted    = false;
  122. static Boolean    gIsLocalNatOn;        // Local NAT on/off
  123. static Boolean    gIsTRCableModem;    // Enable TRCableModem
  124. static Boolean    gIsDNSForwarding;    // Enable DNS Forwarding
  125. static Boolean    gIsOnDemandUp;
  126. static Boolean    gIsOnDemandPending;    // On Demand connection needed
  127. static UInt32    gOnDemandName;        // Hashed OnDemand interface selector
  128. static UInt32    gMonitorName;        // Hashed Monitor interface selector
  129. static UInt32    gOnDemandSrcAddress;// src address of on demand traffic
  130. static UInt16    gFlakePercent;        // 0-100
  131. static UInt16    gFlakeLatency;        // ms
  132.  
  133. // NAT table storage
  134. static translationEntry_t gNatTable0[kNatTableDim];
  135. static translationEntry_t gNatTable1[kNatTableDim];
  136. static translationEntry_t gNatTable2[kNatTableDim];
  137. static translationEntry_t gNatTable3[kNatTableDim];
  138.  
  139. static translationEntry_t* gNatTable[kNatNumDim];
  140.  
  141. // Filter table storage
  142. static FilterEntry_t gFilterTable[kFilterTableDim];
  143.  
  144.  
  145. //--------------------------------------------------------------
  146. // • Proxym STREAMS structures
  147. //--------------------------------------------------------------
  148.  
  149. /*
  150.  * Module information for the streamtab structure
  151.  */
  152. static struct module_info proxym_minfo =        // pushable DLPI streams module
  153. {
  154.     9002,                /* Module Number            */
  155.     "Proxym",            /* Name of module            */
  156.     0,                    /* Minimum data size        */
  157.     INFPSZ,                /* Maximum data size        */
  158.     2048,                /* Hi water mark for queue    */
  159.     128                    /* Lo water mark for queue    */
  160. };
  161.  
  162. /*
  163.  * Info for the "read" queue.
  164.  */
  165.  
  166. static struct qinit proxym_rinit = 
  167. {
  168.     proxym_rput,        /* Put routine for "incoming" data            */
  169.     proxym_rsrv,        /* Service routine for "incoming" data        */
  170.     proxym_open,        /* Our open routine                            */
  171.     proxym_close,         /* Our close routine                        */
  172.     proxy_admin,        /* Our admin routine                        */
  173.     &proxym_minfo,        /* Our module_info                            */
  174. };
  175.  
  176. /*
  177.  * Info for the "write" queue
  178.  */
  179.  
  180. static struct qinit proxym_winit =
  181. {
  182.     proxym_wput,        /* Put routine for client data                    */
  183.     proxym_wsrv,        /* Service routine for client data                */
  184.     0,                    /* open routine goes in read-side structure     */
  185.     0,                    /* close routine goes in read-side structure    */
  186.     0,                    /* admin routine goes in read-side structure    */
  187.     &proxym_minfo        /* Our module_info                                */
  188. };
  189.  
  190. /*
  191.  * The streamtab structure
  192.  */
  193.  
  194. static struct streamtab proxymStreamTab = 
  195. {
  196.     &proxym_rinit,    /* Our read-side qinit structure    */
  197.     &proxym_winit,    /* Our write-side qinit structure    */
  198.     0,                /* Not a mux - no structure info    */
  199.     0                /* Not a mux - no structure info    */
  200. };
  201.  
  202. static struct install_info proxymInstallInfo =
  203. {
  204.     &proxymStreamTab,        // Stream Tab pointer
  205.     kOTModIsModule + kOTModIsFilter, // Tell OT we're a filter module
  206.     SQLVL_QUEUE,            // Synchronization level
  207.     0,                        // Shared writer list buddy
  208.     0,                        // Open Transport use - always set to 0
  209.     0                        // Flag - always set to 0
  210. };
  211.  
  212. //--------------------------------------------------------------
  213. // • Proxy STREAMS structures
  214. //--------------------------------------------------------------
  215.  
  216. /*
  217.  * Module information for the streamtab structure
  218.  */
  219. static struct module_info proxy_minfo =        // TPI streams driver
  220. {
  221.     9003,                /* Module Number            */
  222.     "Proxy",            /* Name of module            */
  223.     0,                    /* Minimum data size        */
  224.     INFPSZ,                /* Maximum data size        */
  225.     2048,                /* Hi water mark for queue    */
  226.     128                    /* Lo water mark for queue    */
  227. };
  228.  
  229. /*
  230.  * Info for the "read" queue.
  231.  */
  232.  
  233. static struct qinit proxy_rinit = 
  234. {
  235.     proxy_rput,            /* Put routine for "incoming" data            */
  236.     proxy_rsrv,            /* Service routine for "incoming" data        */
  237.     proxy_open,            /* Our open routine                            */
  238.     proxy_close,         /* Our close routine                        */
  239.     proxy_admin,        /* Our admin routine                        */
  240.     &proxy_minfo,        /* Our module_info                            */
  241. };
  242.  
  243. /*
  244.  * Info for the "write" queue
  245.  */
  246.  
  247. static struct qinit proxy_winit =
  248. {
  249.     proxy_wput,            /* Put routine for client data                    */
  250.     proxy_wsrv,            /* Service routine for client data                */
  251.     0,                    /* open routine goes in read-side structure     */
  252.     0,                    /* close routine goes in read-side structure    */
  253.     0,                    /* admin routine goes in read-side structure    */
  254.     &proxy_minfo        /* Our module_info                                */
  255. };
  256.  
  257. /*
  258.  * The streamtab structure
  259.  */
  260.  
  261. static struct streamtab proxyStreamTab = 
  262. {
  263.     &proxy_rinit,    /* Our read-side qinit structure    */
  264.     &proxy_winit,    /* Our write-side qinit structure    */
  265.     0,                /* Not a mux - no structure info    */
  266.     0                /* Not a mux - no structure info    */
  267. };
  268.  
  269. static struct install_info proxyInstallInfo =
  270. {
  271.     &proxyStreamTab,        // Stream Tab pointer
  272.     kOTModIsDriver + kOTModUpperIsTPI + kOTModGlobalContext,
  273.     SQLVL_MODULE,            // Synchronization level - the module will never
  274.                             // be re-entered with this setting
  275.     0,                        // Shared writer list buddy
  276.     0,                        // Open Transport use - always set to 0
  277.     0                        // Flag - always set to 0
  278. };
  279.  
  280.  
  281. // ===========================================================================
  282.  
  283. #pragma mark -
  284. #pragma mark ••• Proxym STREAMS Module •••
  285. #pragma mark • module structure & procedures •
  286.  
  287. /*******************************************************************************
  288. ** Open routine
  289. ********************************************************************************/
  290.  
  291.     typedef struct error_struct
  292.     {
  293.         long        reqType;
  294.         queue_t*    rdq;
  295.         int            xtiErr;
  296.         int            macErr;
  297.         Boolean        allocd;
  298.     } error_struct;
  299.     
  300.     typedef struct proxym_struct
  301.     {
  302.         int                myError;
  303.         UInt16            myState;
  304.         UInt16            myProtocolType;
  305.         UInt32            myInterfaceName;
  306.         UInt32            myFastPathHeaderSize;
  307.         UInt16            myPacketCount;        // used for flakeway
  308.         mblk_t*            timerMessage;
  309.         error_struct    myErrorStruct;
  310.         Boolean            errInUse;
  311.     } proxym_struct;
  312.     
  313. int proxym_open(queue_t* rdq, dev_t* devp, int flag, int sflag, cred_t* credp)
  314. {
  315.     int                err;
  316.     proxym_struct*    myData;
  317.     TPortRecord*    thePortRecord;
  318.  
  319.     // adjust ref count so we don't unload until companion module is free
  320.     if ( OTCompareAndSwap32(1, 2, &proxymInstallInfo.ref_count) )
  321.         proxymRefCountAdjusted = true;
  322.     
  323.     err = mi_open_comm(&gProxymListHead, sizeof(proxym_struct),
  324.                         rdq, devp, flag, sflag, credp);
  325.  
  326.     if (err == 0) {
  327.         //     Set my state in my data structure
  328.         myData = (proxym_struct*)rdq->q_ptr;
  329.             
  330.         myData->myState                    = DL_UNBOUND;
  331.         myData->myProtocolType            = 0;
  332.         thePortRecord                     = OTFindPortByDev(*devp);
  333.         myData->myInterfaceName            = HashName(thePortRecord->fPortName);
  334.         myData->myFastPathHeaderSize    = 0;
  335.         //OTKernelPrintf( kOTPrintOnly, "port name: %s.\n", thePortRecord->fPortName);
  336.         myData->errInUse                = false;
  337.         myData->myErrorStruct.allocd    = false;
  338.         // flakeway
  339.         myData->myPacketCount            = 0;
  340.         myData->timerMessage            = nilp(mblk_t);
  341.     }
  342.     //dprintf("\nProxy module opened");
  343.     // return result
  344.     return err;
  345. }
  346.  
  347. /*******************************************************************************
  348. ** Close routine
  349. ********************************************************************************/
  350.  
  351. int proxym_close(queue_t* rdq, int flags, cred_t* credP)
  352. {
  353.     int        err;
  354.     proxym_struct* myData = (proxym_struct*)rdq->q_ptr;
  355.     
  356. //OTKernelPrintf( kOTPrintThenStop, "proxym_close, ref_count: %d, %d.\n",
  357. //    proxymInstallInfo.ref_count, proxyInstallInfo.ref_count);
  358.  
  359.     //  if timerMessage is pending, cancel it
  360.     if (myData->timerMessage) {
  361.         proxym_wsrv(WR(rdq));    // release any waiting messages
  362.         // cancel timer
  363.         mi_timer_free(myData->timerMessage);
  364.         myData->timerMessage = nilp(mblk_t);
  365.     }
  366.     
  367.     err = mi_close_comm(&gProxymListHead, rdq);
  368.  
  369.     // adjust ref count so we don't unload until companion module is free
  370.     if (proxyInstallInfo.ref_count <= 1) {        // if done with companion
  371.         // if I'm done, and my ref_count was adjusted,
  372.         // decrement my ref_count so it can go to zero and
  373.         if (proxymRefCountAdjusted) {
  374.             if ( OTCompareAndSwap32(2, 1, &proxymInstallInfo.ref_count) ) {
  375.                 proxyInstallInfo.ref_count = 0;        // set companion to zero ???
  376.                 proxymRefCountAdjusted = false;        // indicate no longer adjusted
  377.             }
  378.         }
  379.     }
  380.  
  381.     // return result
  382.     return err;
  383. }
  384.  
  385. /*******************************************************************************
  386. ** Admin routine
  387. **
  388. ** Admin routines are for future expansion - just return no error.
  389. ********************************************************************************/
  390.  
  391. int proxy_admin()
  392. {
  393.     return kOTNoError;
  394. }
  395.  
  396. /*******************************************************************************
  397. ** Write-side put routine
  398. ********************************************************************************/
  399.  
  400. int proxym_wput(queue_t* q, mblk_t* mp)
  401. {
  402. //OTKernelPrintf( kOTPrintThenStop, "Entering proxy_wput, db_type: %d.\n", mp->b_datap->db_type);
  403.     /*
  404.      * Process the incoming message from the client
  405.      */
  406.     switch (mp->b_datap->db_type)
  407.     {
  408.             
  409.         /*
  410.          * Request to flush queues.
  411.          */
  412.         case M_FLUSH:
  413.             //    Do the job, then pass the message on
  414.             if ( mp->b_rptr[0] & FLUSHW)
  415.             {
  416.                 if ( (mp->b_rptr[0] & FLUSHBAND) && mp->b_wptr - mp->b_rptr == 2 )
  417.                     flushband(q, mp->b_rptr[1], FLUSHALL);
  418.                 else
  419.                     flushq(q, FLUSHALL);
  420.             }
  421.             if ( mp->b_rptr[0] & FLUSHR )
  422.             {
  423.                 if ( (mp->b_rptr[0] & FLUSHBAND) && mp->b_wptr - mp->b_rptr == 2 )
  424.                     flushband(RD(q), mp->b_rptr[1], FLUSHALL);
  425.                 else
  426.                     flushq(RD(q), FLUSHALL);
  427.             }
  428.             break;
  429.         
  430.         /*
  431.          * Handle data coming from the client
  432.          */
  433.         case M_DATA:
  434.             return proxym_wdata(q, mp);
  435.         
  436.         /*
  437.          * Handle M_PROTO and M_PCPROTO requests coming from the client
  438.          */
  439.         case M_PROTO:
  440.         case M_PCPROTO:
  441.             return proxym_wproto(q, mp);
  442.  
  443.         case M_IOCTL:
  444.         {
  445.             struct iocblk* iocp = (struct iocblk*)mp->b_rptr;
  446.             //dprintf("\nwput IOCTL, ioc_cmd: %x", iocp->ioc_cmd);
  447.             break;
  448.         }
  449.         default:
  450.             break;
  451.     }
  452.     // just pass it on
  453.     putnext(q, mp);
  454.     return 0;
  455. }
  456.  
  457. /*******************************************************************************
  458. ** Read-side put routine
  459. ********************************************************************************/
  460.  
  461. int proxym_rput(queue_t* q, mblk_t* mp)
  462. {
  463. //OTKernelPrintf( kOTPrintThenStop, "Entering proxym_rput, db_type: %d.\n", mp->b_datap->db_type);
  464.     proxym_struct* myData = (proxym_struct*)q->q_ptr;
  465.     /*
  466.      * Process the incoming message from the driver below us
  467.      */
  468.     switch (mp->b_datap->db_type)
  469.     {
  470.             
  471.         /*
  472.          * Request to flush queues.  Do the job, then pass the message on
  473.          */
  474.         case M_FLUSH:
  475.             if ( mp->b_rptr[0] & FLUSHW)
  476.             {
  477.                 if ( (mp->b_rptr[0] & FLUSHBAND) && mp->b_wptr - mp->b_rptr == 2 )
  478.                     flushband(WR(q), mp->b_rptr[1], FLUSHALL);
  479.                 else
  480.                     flushq(WR(q), FLUSHALL);
  481.             }
  482.             if ( mp->b_rptr[0] & FLUSHR )
  483.             {
  484.                 if ( (mp->b_rptr[0] & FLUSHBAND) && mp->b_wptr - mp->b_rptr == 2 )
  485.                     flushband(q, mp->b_rptr[1], FLUSHALL);
  486.                 else
  487.                     flushq(q, FLUSHALL);
  488.             }
  489.             break;
  490.             
  491.         /*
  492.          * Handle data coming from downstream
  493.          */
  494.         case M_DATA:
  495.             return proxym_rdata(q, mp);
  496.         
  497.         /*
  498.          * Handle M_PROTO and M_PCPROTO requests coming from downstream
  499.          */
  500.         case M_PROTO:
  501.         case M_PCPROTO:
  502.             return proxym_rproto(q, mp);
  503.         
  504.         /*
  505.          * If we send any IOCTLs downstream, look at the acks and 
  506.          * nacks here to determine if these are ours.  If so, process
  507.          * them.  Otherwise, just send them on upstream
  508.          */
  509.         case M_IOCACK:
  510.             {
  511.                 struct iocblk* iocp = (struct iocblk*)mp->b_rptr;
  512.                 proxym_struct*    myData = (proxym_struct*)q->q_ptr;
  513.                 mblk_t* cp;
  514.                 //dl_unitdata_ind_t* up;
  515.                 
  516.                 if (iocp->ioc_cmd == DL_IOC_HDR_INFO) {
  517.                     // examine FastPath ACK to determine header size
  518.                     //dprintf("\nproxym_rput DL_IOC_HDR_INFO");
  519.                     //  we expect to see a DL_UNITDATA_IND followed
  520.                     //  by the actual FastPath header
  521.                     cp = mp->b_cont;
  522.                     if (cp == nil) break;
  523.                     //dprintf("\nproxym_rput found attached block type %d prim %0x", cp->b_datap->db_type, up->dl_primitive);
  524.                     //up = (dl_unitdata_ind_t*)cp->b_rptr;
  525.                     //if (up->dl_primitive > 0) {        // observed 0 or 0xffc10000, Mentat says it's a template for DL_UNITDATA_IND
  526.                     if (true) {
  527.                         //dprintf("\nproxym_rput found %0x", up->dl_primitive);
  528.                         // get size of FastPath header
  529.                         cp = cp->b_cont;
  530.                         if (cp == nil) break;
  531.                         //dprintf("\nproxym_rput found attached block");
  532.                         myData->myFastPathHeaderSize = cp->b_wptr - cp->b_rptr;
  533.                         //dprintf("\nproxym_rput FastPathHeaderSize: %d", myData->myFastPathHeaderSize);
  534.                     }
  535.                     
  536.                 }
  537.             }
  538.             break;
  539.  
  540.         case M_IOCNAK:
  541.             break;
  542.  
  543.         case M_PCSIG:
  544.             // record timer has been delivered, so we don't try to cancel it
  545.             myData->timerMessage = nilp(mblk_t);
  546.             // Test if message is valid
  547.             if ( !mi_timer_valid(mp) ) return 0;    // If not valid, ignore it!
  548.             mi_timer_free(mp);                        // free the message
  549.             // release any waiting messages
  550.             proxym_wsrv(WR(q));
  551.             // done
  552.             return 0;            
  553.         /*
  554.          * Anything we don't understand - just pass it on
  555.          */
  556.         default:
  557.             break;
  558.     }
  559.     putnext(q, mp);
  560.     return 0;
  561. }
  562.  
  563. #pragma mark • module support functions •
  564.  
  565.  
  566. /*******************************************************************************
  567. ** Write-side processing routines
  568. ********************************************************************************/
  569.  
  570. int proxym_wdata(queue_t* q, mblk_t* mp)
  571. {
  572.     proxym_struct* myData = (proxym_struct*)RD(q)->q_ptr;
  573.     Boolean result = true;
  574.     mblk_t*            cp;                // message block pointer
  575.     UInt8*            datagram;        // datagram pointer
  576.     FilterEntry_t    filterData;
  577.     SInt32            dataOffset;
  578.     SInt32            dataCount;
  579. //    UInt8            i;
  580.     UInt8            filterAction;
  581.     UInt8            flakeFactor;
  582.     Boolean            flakeAction;    // false=drop, true=pass
  583.     Boolean            match;
  584.     /*    ---------------------------------------------------------------------
  585.         Here, we do whatever munging we're going to do on the client data,
  586.         then send it on.
  587.         Keep in mind that we call this routine from the proxy_wproto routine,
  588.         so that the first block of the message might be an M_PROTO, and not
  589.         data.
  590.         --------------------------------------------------------------------- */
  591.  
  592.     // Check for IP data if protocol is specified
  593.     if ((myData->myProtocolType == kProtocolTypeNone) ||
  594.         (myData->myProtocolType == kProtocolTypeIP)) {
  595.         
  596.         // find datagram and containing message block (put in cp)            
  597.         datagram = FindWDatagram(q, mp, &cp, &dataOffset);
  598.         
  599.         // count data for monitor display    
  600.         if ((myData->myInterfaceName == gMonitorName) || (gMonitorName == 0)) {
  601.             dataCount = proxy_CountMessage(mp) - dataOffset;
  602.             OTAtomicAdd32(dataCount, &mstat.wCount);    
  603.             //OTKernelPrintf( kOTPrintOnly, "proxy_wdata wCount is: %d.\n", mstat.wCount);
  604.         }
  605.  
  606.         
  607.         //
  608.         // for outbound packets: filter first, then NAT
  609.         //
  610.         // Process IP filtering
  611.         filterAction = kFilterNoDial;
  612.         if (datagram != nil) {
  613.             filterData.portName = myData->myInterfaceName;
  614.             filterData.flags = 0;    // kFlagDirectionRead = 0
  615.             filterAction = FilterPacket(datagram, cp, &filterData);
  616.             if (filterAction == kFilterReject) {
  617.                 // kill it
  618.                 freemsg(mp);
  619.                 return 0;
  620.             }
  621.         }
  622.         
  623.         // Traffic for OnDemand interface and interface currently down?
  624.         if ((myData->myInterfaceName == gOnDemandName) &&
  625.             (gIsOnDemandUp == false) &&
  626.             (filterAction != kFilterNoDial) ) {
  627.             // set for OnDemand connection
  628.             gIsOnDemandPending = true;                
  629.         }
  630.  
  631.         // Check if NAT for this interface
  632.         match = false;
  633. //        for (i=0; i<kNatNumDim; i++) {
  634. //            if (myData->myInterfaceName == GetPortName(gNatTable[i])) {
  635. //                // translate message
  636. //                if ((datagram != nil) && GetNatOn(gNatTable[i]) && (myData->myInterfaceName)) {
  637. //                    result = Convert2Apparent(gNatTable[i], datagram, cp, kNATOptionIPMasq);
  638. //                    match = true;
  639. //                }
  640. //                break;
  641. //            }
  642. //        }
  643.         
  644.         if (!match) {
  645.             // if no match try to NAT for DNS forwarding
  646. //            if ((datagram != nil) && GetNatOn(gNatTable[0]) && gIsDNSForwarding) {
  647. //                result = Convert2Apparent(gNatTable[0], datagram, cp, kNATOptionDNS);
  648. //            }
  649.         }
  650.         
  651.     }
  652.  
  653.     // flakeway - (1) delete packets
  654.     if (gFlakePercent > 0) {
  655.         flakeFactor = 100/gFlakePercent;
  656.         flakeAction = false;    // drop 1 in every flakeFactor packets
  657.         if (gFlakePercent > 50) {
  658.             flakeFactor = 100/(100-gFlakePercent);
  659.             flakeAction = true; // pass 1 in every flakeFactor packets
  660.         }
  661.         myData->myPacketCount += 1;
  662.         if ((myData->myPacketCount % flakeFactor) == 0) {
  663.             // action for 1 in every N packets
  664.             if (flakeAction == false) {
  665.                 // drop packet
  666.                 freemsg(mp);
  667.                 return 0;
  668.             }
  669.         }
  670.         else {
  671.             // action for other N-1 packets
  672.             if (flakeAction) {
  673.                 // drop packet
  674.                 freemsg(mp);
  675.                 return 0;
  676.             }
  677.         }
  678.     }
  679.  
  680.  
  681.     // flakeway - (2) delay packets
  682.     if (gFlakeLatency > 0) {
  683.         // create a new timer message if needed
  684.         if (!myData->timerMessage) {
  685.             // try to allocate a timer message (q, size)
  686.             myData->timerMessage = mi_timer_alloc(RD(q), kTimerSize);
  687.             //  schedule message
  688.             if (myData->timerMessage) {
  689.                 // schedule for delay milliseconds
  690.                 mi_timer(myData->timerMessage, gFlakeLatency);
  691.             }
  692.         }
  693.         // if we have a timer, queue message to process when timer expires
  694.         if (myData->timerMessage) {
  695.             putq(q, mp);
  696.             return 0;
  697.         }
  698.     }
  699.          
  700.     /*
  701.      * Now, we send it on.  If we can't because of flow control, use
  702.      * putq to put it on our queue and send it on.
  703.      */
  704.     if ( !bcanput(q->q_next, mp->b_band) )
  705.          putq(q, mp);
  706.     else
  707.         putnext(q, mp);
  708.  
  709.     return 0;
  710. }
  711.  
  712. int proxym_wproto(queue_t* q, mblk_t* mp)
  713. {
  714.     Boolean            doOutState = false;
  715.     proxym_struct*    myData = (proxym_struct*)RD(q)->q_ptr;
  716.     /*
  717.      * If the message block is not big enough - blow it away
  718.      */
  719.     if ( mp->b_wptr - mp->b_rptr < sizeof(long) )
  720.     {
  721.         freemsg(mp);
  722.         return 0;
  723.     }
  724.     /*
  725.      * Look at the incoming primitive message
  726.      */
  727.  
  728.     switch ( ((union DL_primitives*)mp->b_rptr)->dl_primitive )
  729.     {
  730.         /*
  731.          * For incoming data, let proxym_wdata handle it
  732.          */
  733.         case DL_UNITDATA_REQ:
  734.             return proxym_wdata(q, mp);
  735.  
  736.         case DL_INFO_REQ:                
  737.             /*
  738.             nextinfo = q->q_next->q_qinfo->qi_minfo;
  739.             OTKernelPrintf( kOTPrintOnly, "DL_INFO_REQ, next write module is: %s.\n", nextinfo->mi_idname);
  740.             nextinfo = RD(q)->q_next->q_qinfo->qi_minfo;
  741.             OTKernelPrintf( kOTPrintOnly, "DL_INFO_REQ, next read module is: %s.\n", nextinfo->mi_idname);
  742.             */
  743.             //dprintf("\nproxym_wproto DL_INFO_REQ");
  744.             break;
  745.         
  746.         case DL_BIND_REQ:
  747.             /*
  748.              * If we're not in the unbound state, give a
  749.              * TOUTSTATE error.  Otherwise, change our
  750.              * state to DL_BIND_PENDING to flag that we're in
  751.              * the process of binding, and pass the bind on.
  752.              */
  753.             if ( myData->myState != DL_UNBOUND )
  754.                 doOutState = true;
  755.             else {
  756.                 myData->myState = DL_BIND_PENDING;
  757.             }
  758.             //dprintf("\nproxym_wproto DL_BIND_REQ");
  759.             break;
  760.             
  761.         case DL_UNBIND_REQ:
  762.             /*
  763.              * If we're not in the DL_IDLE or DL_BIND_PENDING states,
  764.              * give a TOUTSTATE error.  Otherwise, pass the unbind on.
  765.              */
  766.             if ( myData->myState != DL_IDLE && myData->myState != DL_BIND_PENDING )
  767.                 doOutState = true;
  768.             //dprintf("\nproxym_wproto DL_UNBIND_REQ");
  769.             break;
  770.             
  771.         default:
  772.             // pass it on
  773.             //dprintf("\nproxym_wproto prim_type: %d", ((union DL_primitives*)mp->b_rptr)->dl_primitive);
  774.             break;
  775.     }
  776.     if ( doOutState )
  777.     {
  778.         ReplyErrorAck(RD(q), mp, ((union DL_primitives*)mp->b_rptr)->dl_primitive,
  779.                       TOUTSTATE, 0);
  780.         return 0;
  781.     }
  782.     /*
  783.      * Here, we just pass the message block on to the next layer, or
  784.      * queue it up till flow control is lifted.
  785.      */
  786.     if (mp->b_datap->db_type > QPCTL || canput(q->q_next) )
  787.         putnext(q, mp);
  788.     else
  789.         putq(q, mp);
  790.     return 0;
  791.  
  792. }
  793.  
  794. int proxym_wsrv(queue_t* q)
  795. {
  796.     mblk_t*    mp;
  797.     proxym_struct* myData = (proxym_struct*)RD(q)->q_ptr;
  798.     
  799.     // if waiting for flake Latency just return
  800.     if (myData->timerMessage != 0) return 0;
  801.     
  802.     /*
  803.      * Send on downstream anything that was scheduled for flow control!
  804.      */
  805.     while ( (mp = getq(q)) != nilp(mblk_t) )
  806.     {
  807.         /*
  808.          * If we're flow controlled, get out and we'll come back when the flow-
  809.          * control lifts.
  810.          */
  811.         if ( !bcanput(q->q_next, mp->b_band) )
  812.         {
  813.             putbq(q, mp);
  814.             return 0;
  815.         }
  816.         /*
  817.          * Otherwise, send the data downstream, and get some more
  818.          */
  819.         //OTKernelPrintf( kOTPrintThenStop, "wsrv, putnext \n");
  820.         putnext(q, mp);
  821.     }
  822.     return 0;
  823. }
  824.  
  825. /*******************************************************************************
  826. ** Read-side process routines
  827. ********************************************************************************/
  828.  
  829. int proxym_rdata(queue_t* q, mblk_t* mp)
  830. {
  831.     proxym_struct* myData = (proxym_struct*)q->q_ptr;
  832.     Boolean result = true;
  833.     mblk_t* cp;                // message block pointer
  834.     UInt8*    datagram;        // datagram pointer
  835.     SInt32    dataOffset;
  836.     SInt32    dataCount;
  837.     FilterEntry_t filterData;
  838. //    UInt8    i;
  839.     Boolean    match;
  840.     /*
  841.      * If we're not ready for incoming data, just free it up
  842.      */
  843.     if ( myData->myState != DL_IDLE )
  844.     {
  845.         freemsg(mp);
  846.         return 0;
  847.     }
  848.     
  849.     /*    ---------------------------------------------------------------------
  850.         Here, we do whatever munging we're going to do on the incoming data,
  851.         then send it on.
  852.         Keep in mind that we call this routine from the proxy_rproto routine,
  853.         so that the first block of the message might be an M_PROTO, and not
  854.         data.
  855.         --------------------------------------------------------------------- */
  856.  
  857.     // Check for IP data if protocol is specified
  858.     if ((myData->myProtocolType == kProtocolTypeNone) ||
  859.         (myData->myProtocolType == kProtocolTypeIP)) {
  860.  
  861.         // find datagram and containing message block (put in cp)            
  862.         datagram = FindRDatagram(q, mp, &cp, &dataOffset);
  863.         // count data for monitor display
  864.         if ((myData->myInterfaceName == gMonitorName) || (gMonitorName == 0)) {
  865.             dataCount = proxy_CountMessage(mp) - dataOffset;
  866.             OTAtomicAdd32(dataCount, &mstat.rCount);    
  867.             //OTKernelPrintf( kOTPrintOnly, "proxy_rdata rCount is: %d.\n", mstat.rCount);
  868.         }
  869.  
  870.         //
  871.         // for inbound packets: NAT first, then filter
  872.         //
  873.         // Check if NAT for this interface
  874.         match = false;
  875. //        for (i=0; i<kNatNumDim; i++) {
  876. //            if (myData->myInterfaceName == GetPortName(gNatTable[i])) {
  877. //                // translate message
  878. //                if ((datagram != nil) && GetNatOn(gNatTable[i]) && (myData->myInterfaceName)) {
  879. //                    match = true;
  880. //                    result = Convert2Actual(gNatTable[i], datagram, cp, kNATOptionIPMasq);
  881. //                    // if no translation found and no exposed host
  882. //                    if (result == kNATActionReject) {
  883. //                        // kill it
  884. //                        freemsg(mp);
  885. //                        return 0;        
  886. //                    }
  887. //                }
  888. //                break;
  889. //            }
  890. //        }
  891.         // if no match, perform local translation if any
  892.         if (!match) {
  893.             // translate message
  894. /*
  895.             if ((datagram != nil) && GetNatOn(gNatTable[0])) {
  896.                 if (gIsTRCableModem) {
  897.                     // TR Cable Modem
  898. //                    result = Convert2Actual(gNatTable[0], datagram, cp, kNATOptionIPMasq);                
  899.                 }
  900.                 else
  901.                 if (gIsLocalNatOn) {
  902. //                    result = Convert2Actual(gNatTable[0], datagram, cp, kNATOptionLocal);
  903.                     //if (result && !gIsTRCableModem) {
  904.                     //    // for Local NAT, direct response via gateway
  905.                     //    result = Convert2Apparent(gNatTable[0], datagram, cp, kNATOptionLocal);
  906.                     //}
  907.                 }
  908.                 else
  909.                 if (gIsDNSForwarding) {
  910.                     // DNS Forwarding
  911. //                    result = Convert2Actual(gNatTable[0], datagram, cp, kNATOptionDNS);                
  912.                 }
  913.             }
  914. */
  915.         }
  916.  
  917.         // Process IP filtering
  918.         if (datagram != nil) {
  919.             UInt8    filterAction;
  920.             filterData.portName = myData->myInterfaceName;
  921.             filterData.flags = kFlagDirectionRead;
  922.             filterAction = FilterPacket(datagram, cp, &filterData);
  923.             if (filterAction == kFilterReject) {
  924.                 // kill it
  925.                 freemsg(mp);
  926.                 return 0;
  927.             }
  928.         }
  929.  
  930.     }
  931.  
  932.     /*
  933.      * Now, we send it on.  If we can't because of flow control, use
  934.      * putq to put it on our queue and send it on later.
  935.      */
  936.     if ( !bcanput(q->q_next, mp->b_band) )
  937.          putq(q, mp);
  938.     else
  939.         putnext(q, mp);
  940.     
  941.     return 0;
  942. }
  943.  
  944. int proxym_rproto(queue_t* q, mblk_t* mp)
  945. {
  946.     Boolean            doOutState = false;
  947.     proxym_struct*    myData = (proxym_struct*)q->q_ptr;
  948.     dl_info_ack_t*    myInfo;
  949. //    UInt8*            dp;
  950.     /*
  951.      * If the message block is not big enough - blow it away
  952.      */
  953.     if ( mp->b_wptr - mp->b_rptr < sizeof(long) )
  954.     {
  955.         freemsg(mp);
  956.         return 0;
  957.     }
  958.     /*
  959.      * Look at the incoming primitive message
  960.      */
  961.     switch ( ((union DL_primitives*)mp->b_rptr)->dl_primitive )
  962.     {
  963.         /*
  964.          * For incoming data, let proxy_rdata handle it
  965.          */
  966.         case DL_UNITDATA_IND:
  967.             return proxym_rdata(q, mp);
  968.  
  969.         case DL_INFO_ACK:
  970.             myInfo = (dl_info_ack_t*)mp->b_rptr;
  971.             //dprintf("\nproxym_rproto DL_INFO_ACK");
  972. /*            
  973.             dprintf("\n dl_max_sdu: %d", myInfo->dl_max_sdu);
  974.             dprintf("\n dl_min_sdu: %d", myInfo->dl_min_sdu);
  975.             dprintf("\n dl_addr_length: %d", myInfo->dl_addr_length);
  976.             dprintf("\n dl_mac_type: %d", myInfo->dl_mac_type);
  977.             dprintf("\n dl_current_state: %d", myInfo->dl_current_state);
  978.             dprintf("\n dl_sap_length: %d", myInfo->dl_sap_length);
  979.             dprintf("\n dl_service_mode: %d", myInfo->dl_service_mode);
  980.             dprintf("\n dl_qos_length: %d", myInfo->dl_qos_length);
  981.             dprintf("\n dl_qos_offset: %d", myInfo->dl_qos_offset);
  982.             dprintf("\n dl_qos_range_length: %d", myInfo->dl_qos_range_length);
  983.             dprintf("\n dl_qos_range_offset: %d", myInfo->dl_qos_range_offset);
  984.             dprintf("\n dl_provider_style: %d", myInfo->dl_provider_style);
  985.             dprintf("\n dl_addr_offset: %d", myInfo->dl_addr_offset);
  986.             dprintf("\n dl_version: %d", myInfo->dl_version);
  987.             dprintf("\n dl_brdcst_addr_length: %d", myInfo->dl_brdcst_addr_length);
  988.             dprintf("\n dl_brdcst_addr_offset: %d", myInfo->dl_brdcst_addr_offset);
  989.             dprintf("\n dl_growth: %d", myInfo->dl_growth);
  990.             dp = (UInt8*)myInfo;
  991.             dprintf("\n dl_sap_addr: ");
  992.             dprintmem(&dp[myInfo->dl_addr_offset], myInfo->dl_addr_length);
  993. */
  994.             break;
  995.                     
  996.         /*
  997.          * Here, a bind request succeeded.
  998.          */
  999.         case DL_BIND_ACK: {
  1000.             // remember what protocol we are bound to
  1001.             UInt32            sap;
  1002.             dl_bind_ack_t*    bindAck;
  1003.             bindAck = (dl_bind_ack_t*)mp->b_rptr;
  1004.             sap = bindAck->dl_sap;
  1005.             if ((kMinDIXSAP <= sap) && (sap <= kMaxDIXSAP)) {
  1006.                 myData->myProtocolType = bindAck->dl_sap & 0xFFFF;
  1007.                 //dprintf("\nproxym_rproto DL_BIND_ACK, protocol type: %x", myData->myProtocolType);
  1008.             }
  1009.             // update endpoint state
  1010.             myData->myState = DL_IDLE;
  1011.             break;
  1012.         }    
  1013.         /*
  1014.          * Handle any error acks that come back
  1015.          */
  1016.         case DL_ERROR_ACK:
  1017.         {
  1018.             switch ( ((dl_error_ack_t*)mp->b_rptr)->dl_error_primitive )
  1019.             {
  1020.                 /*
  1021.                  * If the unbind failed, then we are not unbound either.
  1022.                  * Send the error on up to the client.
  1023.                  */
  1024.                 case DL_UNBIND_REQ:
  1025.                     myData->myState = DL_IDLE;
  1026.                     //dprintf("\nproxym_rproto DL_ERROR_ACK on DL_UNBIND_REQ");
  1027.                     break;
  1028.                     
  1029.                 /*
  1030.                  * If the bind failed, we fall back to the unbound state
  1031.                  */
  1032.                 case DL_BIND_REQ:
  1033.                     myData->myState = DL_UNBOUND;
  1034.                     //dprintf("\nproxym_rproto DL_ERROR_ACK on DL_BIND_REQ");
  1035.                     break;
  1036.                     
  1037.                  
  1038.                 /*
  1039.                  * Any error acks we don't understand just pass on
  1040.                  */
  1041.                 default:
  1042.                     //dprintf("\nproxym_rproto DL_ERROR_ACK on prim: %d", ((dl_ok_ack_t*)mp->b_rptr)->dl_correct_primitive);
  1043.                     break;
  1044.             }
  1045.             break;
  1046.         }
  1047.         
  1048.         /*
  1049.          * Handle any OK acks that come back
  1050.          */
  1051.         case DL_OK_ACK:
  1052.         {
  1053.             switch ( ((dl_ok_ack_t*)mp->b_rptr)->dl_correct_primitive )
  1054.             {
  1055.                 /*
  1056.                  * If the unbind is OK, we are no longer unbound.
  1057.                  */
  1058.                 case DL_UNBIND_REQ:
  1059.                     myData->myState = DL_UNBOUND;
  1060.                     //dprintf("\nproxym_rproto DL_OK_ACK on DL_UNBIND_REQ");
  1061.                     break;
  1062.  
  1063.                 case DL_BIND_REQ:
  1064.                     myData->myState = DL_IDLE;
  1065.                     //dprintf("\nproxym_rproto DL_OK_ACK on DL_BIND_REQ");
  1066.                     break;
  1067.                                         
  1068.                 /*
  1069.                  * Any error acks we don't understand just pass on
  1070.                  */
  1071.                 default:
  1072.                     //dprintf("\nproxym_rproto DL_OK_ACK on prim: %d", ((dl_ok_ack_t*)mp->b_rptr)->dl_correct_primitive);
  1073.                     break;
  1074.             }
  1075.             break;
  1076.         }
  1077.                             
  1078.         /*
  1079.          * Anything else we don't understand, just send it on
  1080.          */
  1081.         default:
  1082.             //dprintf("\nproxym_rproto prim_type: %d", ((union DL_primitives*)mp->b_rptr)->dl_primitive);
  1083.             break;
  1084.     }    /*
  1085.      * Here, we just pass the message block on to the next layer, or
  1086.      * queue it up till flow control is lifted.
  1087.      */
  1088.     if (mp->b_datap->db_type > QPCTL || canput(q->q_next) )
  1089.         putnext(q, mp);
  1090.     else
  1091.         putq(q, mp);
  1092.     return 0;
  1093. }
  1094.  
  1095. int proxym_rsrv(queue_t* q)
  1096. {
  1097.     mblk_t*    mp;
  1098.     /*
  1099.      * Send on up anything that was scheduled for flow control!
  1100.      */
  1101.     while ( (mp = getq(q)) != nilp(mblk_t) )
  1102.     {
  1103.         /*
  1104.          * If we're flow controlled, get out and we'll come back when the flow-
  1105.          * control lifts.
  1106.          */
  1107.         if ( !bcanput(q->q_next, mp->b_band) )
  1108.         {
  1109.             putbq(q, mp);
  1110.             return 0;
  1111.         }
  1112.         /*
  1113.          * Otherwise, send the data upstream, and get some more
  1114.          */
  1115.         putnext(q, mp);
  1116.     }
  1117.     return 0;
  1118. }
  1119.  
  1120. #pragma mark • generic support functions •
  1121.  
  1122. /*******************************************************************************
  1123. ** ReuseMessage
  1124. **
  1125. ** Determine if we can reuse an mblk_t*.  If not, reallocate one.
  1126. ********************************************************************************/
  1127.  
  1128. mblk_t* ReuseMessage(mblk_t* mp, size_t size)
  1129. {
  1130.     if ( mp != nilp(mblk_t) )
  1131.     {
  1132.         if ( mp->b_cont != nilp(mblk_t) )
  1133.         {
  1134.             freemsg(mp->b_cont);
  1135.             mp->b_cont = nilp(mblk_t);
  1136.         }
  1137.         mp->b_rptr = mp->b_datap->db_base;
  1138.         mp->b_wptr = mp->b_rptr;
  1139.         if ( mp->b_datap->db_ref == 1 &&
  1140.              mp->b_datap->db_lim - mp->b_rptr >= size )
  1141.             return mp;
  1142.         freemsg(mp);
  1143.     }
  1144.     return allocb(size, BPRI_LO);
  1145. }
  1146.  
  1147. /*******************************************************************************
  1148. ** proxy_error
  1149. **
  1150. ** Process a fatal error
  1151. ********************************************************************************/
  1152.  
  1153.     static void retry_error(long arg)
  1154.     {
  1155.         proxym_struct* myData = (proxym_struct*)((queue_t*)arg)->q_ptr;
  1156.         (void)proxy_error((queue_t*)arg, NULL, myData->myError);
  1157.     }
  1158.     
  1159. int proxy_error(queue_t* rdq, mblk_t* mp, int error)
  1160. {
  1161.     proxym_struct* myData = (proxym_struct*)rdq->q_ptr;
  1162.     myData->myState = DL_UNATTACHED;    // a bad state (any data will be ignored)
  1163.     /*
  1164.      * Try to reuse the incoming message block.
  1165.      */
  1166.     mp = ReuseMessage(mp, 1);
  1167.     /*
  1168.      * If we can't get one, use bufcall to try this again
  1169.      * when memory is available.
  1170.      */
  1171.     if ( mp == nilp(mblk_t) )
  1172.     {
  1173.         myData->myError = error;
  1174.         bufcall(1, BPRI_HI, (bufcall_t)retry_error, (long)rdq);
  1175.         return 0;
  1176.     }
  1177.     mp->b_wptr = mp->b_rptr + 1;
  1178.     mp->b_rptr[0] = (unsigned char)error;
  1179.     mp->b_datap->db_type = M_ERROR;
  1180.     putnext(rdq, mp);
  1181.     return 0;
  1182. }
  1183.  
  1184. /*******************************************************************************
  1185. ** ReplyErrorAck
  1186. ********************************************************************************/
  1187.  
  1188.     static void retry_ack(long arg)
  1189.     {
  1190.         error_struct* es = (error_struct*)arg;
  1191.         int    xtiErr    = es->xtiErr;
  1192.         int macErr    = es->macErr;
  1193.         long reqType    = es->reqType;
  1194.         queue_t* rdq    = es->rdq;
  1195.         if ( es->allocd )
  1196.             OTFreeMem(es);
  1197.         ReplyErrorAck(rdq, NULL, reqType, xtiErr, macErr);
  1198.     }
  1199.     
  1200. void ReplyErrorAck(queue_t* rdq, mblk_t* mp, long reqType, int xtiErr, int macErr)
  1201. {
  1202.     proxym_struct* myData = (proxym_struct*)rdq->q_ptr;
  1203.     mp = ReuseMessage(mp, sizeof(dl_error_ack_t));
  1204.     if ( mp == nilp(mblk_t) )
  1205.     {
  1206.         /*
  1207.          * If we can't get a message block, either allocate an error_struct
  1208.          * or use the one we have stored in our data.
  1209.          */
  1210.         error_struct* es;
  1211.         if ( myData->errInUse )
  1212.         {
  1213.             es = (error_struct*)OTAllocMem(sizeof(error_struct*));
  1214.             if ( es != NULL )
  1215.                 es->allocd = true;
  1216.         }
  1217.         else
  1218.         {
  1219.             myData->errInUse    = true;
  1220.             es = &myData->myErrorStruct;
  1221.         }
  1222.         /*
  1223.          * If we could get an error_struct, try using bufcall.  If that fails -
  1224.          * we're hosed.  Use proxy_error to kill the stream
  1225.          */
  1226.         if ( es != NULL )
  1227.         {
  1228.             es->reqType    = reqType;
  1229.             es->xtiErr    = xtiErr;
  1230.             es->macErr    = macErr;
  1231.             es->rdq        = rdq;
  1232.             if ( bufcall(sizeof(dl_error_ack_t), BPRI_HI, (bufcall_t)retry_ack,
  1233.                          (long)es) != 0 )
  1234.             {
  1235.                 if ( es->allocd )
  1236.                     OTFreeMem(es);
  1237.                 es = NULL;
  1238.             }
  1239.         }
  1240.         if ( es == NULL )
  1241.             (void)proxy_error(rdq, NULL, ENOSR);
  1242.     } else {
  1243.         mp->b_wptr = mp->b_rptr + sizeof(dl_error_ack_t);
  1244.         ((dl_error_ack_t*)mp->b_rptr)->dl_primitive = DL_ERROR_ACK;
  1245.         ((dl_error_ack_t*)mp->b_rptr)->dl_error_primitive = reqType;
  1246.         ((dl_error_ack_t*)mp->b_rptr)->dl_errno = xtiErr;
  1247.         ((dl_error_ack_t*)mp->b_rptr)->dl_unix_errno = macErr;
  1248.         mp->b_datap->db_type = M_PCPROTO;
  1249.         putnext(rdq, mp);
  1250.     }
  1251. }
  1252.  
  1253.  
  1254. // ---------------------------------------------------------------------------------
  1255. //    • proxy count message
  1256. // ---------------------------------------------------------------------------------
  1257. //    Count data characters in message
  1258. SInt32 proxy_CountMessage(mblk_t* mp)
  1259. {
  1260.     mblk_t* cp = mp;        // local copy of mp
  1261.     SInt32 count = 0;
  1262.  
  1263.     // don't count first block if it's an M_PROTO (such as DL_UNITDATA_REQ/IND)
  1264.     if ( cp->b_datap->db_type == M_PROTO ) cp = cp->b_cont;
  1265.  
  1266.     // count characters in first block and any continuation blocks
  1267.     while (cp != nilp(mblk_t)) {
  1268.         count += (UInt32)cp->b_wptr - (UInt32)cp->b_rptr;
  1269.         cp = cp->b_cont;
  1270.     }
  1271.     return count;
  1272. }
  1273.  
  1274.  
  1275. // ---------------------------------------------------------------------------------
  1276. //    • Hash Name
  1277. // ---------------------------------------------------------------------------------
  1278. //    Hash module name to a 32-bit value
  1279. //    The hashed value is used to select which drivers we will monitor or translate
  1280. UInt32 HashName(char* inName)
  1281. {
  1282.     UInt32    result = 0;
  1283.     UInt32    part = 0;
  1284.     UInt32    index = 0;
  1285.     
  1286.     while (inName[index] != 0) {
  1287.         part = result >> 24;        // get left most byte
  1288.         result = result << 8;        // shift left 8-bits
  1289.         result += inName[index];    // add next character in name
  1290.         result += part << 5;        // add back anything shifted out
  1291.         result += part << 19;
  1292.         index += 1;                    // increment to get next character
  1293.     }
  1294.     
  1295.     return result;
  1296. }
  1297.  
  1298.  
  1299. // ---------------------------------------------------------------------------------
  1300. //    • FindWDatagram
  1301. // ---------------------------------------------------------------------------------
  1302. //    Find start of IP datagram
  1303. //    Returns nil if none found
  1304. UInt8*
  1305. FindWDatagram(queue_t* q, mblk_t* mp, mblk_t** outMp, SInt32* dataOffset)
  1306. {
  1307.     mblk_t* cp;                // message block pointer
  1308.     UInt8*    datagram;
  1309.     proxym_struct* myData = (proxym_struct*)RD(q)->q_ptr;
  1310.  
  1311.     // find start of datagram
  1312.     datagram = nil;
  1313.     cp = mp;        // local copy of mp
  1314.     *dataOffset = 0;
  1315.  
  1316.     if ( cp->b_datap->db_type == M_PROTO ) {
  1317.         // first block is an M_PROTO
  1318.         //   DL_UNITDATA_REQ/IND with datagram in attached M_DATA blocks                    
  1319.         cp = cp->b_cont;
  1320.         if (cp != nilp(mblk_t)) {
  1321.             // pull up message if necessary
  1322.             if (cp->b_cont != nil) pullupmsg(cp, -1);
  1323.             datagram = cp->b_rptr;
  1324.         }
  1325.     } else {
  1326.         // first block is M_DATA
  1327.         //   Mentat Fastpath M_DATA message with Link Layer header                    
  1328.         // We listen for the DL_IOC_HDR_INFO ack and examine the
  1329.         //   Header to determine its length.  See Mentat 3-61.
  1330.         // pull up message if necessary
  1331.         UInt32 hLen = myData->myFastPathHeaderSize;
  1332.         if (cp->b_cont != nil) pullupmsg(cp, -1);
  1333.         datagram = cp->b_rptr;
  1334.  
  1335.         // use FastPathHeaderSize if reasonable
  1336.         if ((hLen > 0) &&                                // size is specified
  1337.             ((datagram[hLen] & 0xF0) == 0x40)) {        // points to start of IP V4 datagram
  1338.             datagram = &datagram[hLen];
  1339.             *dataOffset = hLen;
  1340.         }
  1341.         else {
  1342.             // fallback to look for start of datagram
  1343.             if ((datagram[0] & 0xF0) != 0x40) {
  1344.                 int i;
  1345.                 for (i=14; i>=0; i-=2) {
  1346.                     if (datagram[i] == 0x45) {
  1347.                         datagram = &datagram[i];
  1348.                         *dataOffset = i;
  1349.                         break;
  1350.                     }
  1351.                 }
  1352.             }
  1353.         }
  1354.     }
  1355.  
  1356.     *outMp = cp;
  1357.     return datagram;
  1358. }
  1359.  
  1360.  
  1361. // ---------------------------------------------------------------------------------
  1362. //    • FindRDatagram
  1363. // ---------------------------------------------------------------------------------
  1364. //    Find start of IP datagram
  1365. //    Returns nil if none found
  1366. UInt8*
  1367. FindRDatagram(queue_t* q, mblk_t* mp, mblk_t** outMp, SInt32* dataOffset)
  1368. {
  1369.     mblk_t* cp;                // message block pointer
  1370.     UInt8*    datagram;
  1371.  
  1372.     // find start of datagram
  1373.     datagram = nil;
  1374.     cp = mp;        // local copy of mp
  1375.     *dataOffset = 0;
  1376.  
  1377.     if ( cp->b_datap->db_type == M_PROTO ) {
  1378.         // first block is an M_PROTO
  1379.         //   DL_UNITDATA_REQ/IND with datagram in attached M_DATA blocks                    
  1380.         cp = cp->b_cont;
  1381.         if (cp != nilp(mblk_t)) {
  1382.             // pull up message if necessary
  1383.             if (cp->b_cont != nil) pullupmsg(cp, -1);
  1384.             datagram = cp->b_rptr;
  1385.         }
  1386.     } else {
  1387.         // first block is M_DATA
  1388.         //   Mentat Fastpath M_DATA message with no link layer header (read side)
  1389.         // pull up message if necessary
  1390.         if (cp->b_cont != nil) pullupmsg(cp, -1);
  1391.         datagram = cp->b_rptr;
  1392.     }
  1393.  
  1394.     *outMp = cp;
  1395.     return datagram;
  1396. }
  1397.  
  1398.  
  1399. // ---------------------------------------------------------------------------------
  1400. //    • FilterPacket
  1401. // ---------------------------------------------------------------------------------
  1402. // Perform IP filtering
  1403. // Include NetBIOS filtering as standard for On Demand Interface
  1404. //   Look for UDP from source ports 137, 138, and 139
  1405. UInt8
  1406. FilterPacket(UInt8* datagram, mblk_t* mp, FilterEntry_t* filterData)
  1407. {
  1408.     ip_header_t*    ipHeader;
  1409.     udp_header_t*    udpHeader;
  1410.     tcp_header_t*    tcpHeader;
  1411.     icmp_header_t*    icmpHeader;
  1412.     UInt32            size;
  1413.     UInt8            ipHeaderLen;
  1414.     UInt8            result;
  1415.  
  1416.     do {    
  1417.         // default to rejct if unrecognized
  1418.         result = kFilterReject;
  1419.         
  1420.         size = (UInt32)mp->b_wptr - (UInt32)datagram;
  1421.         // make sure we got enough data for IP header
  1422.         if (size < 20) {
  1423.             break;
  1424.         }
  1425.         
  1426.         // setup to access IP Header
  1427.         ipHeader = (ip_header_t*)datagram;
  1428.  
  1429.         // check that we have a valid datagram
  1430.         // Is it V4?
  1431.         if ((ipHeader->hlen & 0xF0) != 0x40) {
  1432.             break;
  1433.         }
  1434.         ipHeaderLen = (ipHeader->hlen & 0x0F) << 2;    // in bytes
  1435.         // *** optional, verify header checksum
  1436. //        if (IpSum( (UInt16*)&datagram[0], (UInt16*)&datagram[ipHeaderLen] ) != 0xFFFF) {
  1437. //            break;
  1438. //        }
  1439.         
  1440.         // get IP address
  1441.         filterData->sourceNet.address = ipHeader->srcAddress;
  1442.         filterData->destNet.address    = ipHeader->dstAddress;
  1443.         if (filterData->portName == gOnDemandName) {
  1444.             gOnDemandSrcAddress    = ipHeader->srcAddress;        // remember on demand src
  1445.         }
  1446.         // get protocol
  1447.         filterData->protocol = ipHeader->protocol;
  1448.         
  1449.         result = kFilterPass;
  1450.         // Handle each protocol as a separate case
  1451.         switch (ipHeader->protocol) {
  1452.             case kProtocolUDP:
  1453.                 // make sure we got enough data for UDP header
  1454.                 if (size < (ipHeaderLen + 8)) break;
  1455.                 // setup access to UDP header
  1456.                 udpHeader = (udp_header_t*)&datagram[ipHeaderLen];
  1457.                 // get UDP protocol ports
  1458.                 filterData->sourcePorts.lo = udpHeader->srcPort;
  1459.                 filterData->destPorts.lo = udpHeader->dstPort;                
  1460.                 // filter NetBIOS DNS querries
  1461.                 if ((filterData->portName == gOnDemandName) &&         // on demand interface
  1462.                     ((filterData->flags & kFlagDirectionRead) == 0)) { // write side
  1463.                     if ((udpHeader->srcPort == 137) ||
  1464.                         (udpHeader->srcPort == 138) ||
  1465.                         (udpHeader->srcPort == 139)) {
  1466.                         result = kFilterNoDial;
  1467.                         break;
  1468.                     }
  1469.                 }
  1470.                 // process through filter table
  1471. //                result = FilterDatagram(gFilterTable, filterData);
  1472.                 break;
  1473.                 
  1474.             case kProtocolTCP:
  1475.                 // make sure we got enough data for TCP header
  1476.                 if (size < (ipHeaderLen + 20)) break;
  1477.                 // setup access to TCP header
  1478.                 tcpHeader = (tcp_header_t*)&datagram[ipHeaderLen];
  1479.                 // get TCP protocol ports
  1480.                 filterData->sourcePorts.lo = tcpHeader->srcPort;
  1481.                 filterData->destPorts.lo = tcpHeader->dstPort;                
  1482.                 // get TCP Ack bit
  1483.                 if (tcpHeader->code & kCodeACK) {
  1484.                     filterData->flags |= kFlagAck;
  1485.                 }
  1486.                 // process through filter table
  1487. //                result = FilterDatagram(gFilterTable, filterData);
  1488.                 if ((result == kFilterPass) && (tcpHeader->code & kCodeFIN)) result = kFilterNoDial;                
  1489.                 break;
  1490.  
  1491.             case kProtocolICMP:
  1492.                 // make sure we got the whole datagram
  1493.                 if (size < ipHeader->totalLength) break;
  1494.                 // setup access to ICMP header
  1495.                 icmpHeader = (icmp_header_t*)&datagram[ipHeaderLen];
  1496.                 // use ICMP type in place of protocol port
  1497.                 filterData->sourcePorts.lo = icmpHeader->type;
  1498.                 filterData->destPorts.lo = icmpHeader->code;
  1499.                 // process through filter table
  1500. //                result = FilterDatagram(gFilterTable, filterData);
  1501.                 // acquire flakeway parameters
  1502.                 {
  1503.                     enum { kMagic = 'sqlh' };
  1504.                     UInt32 magic;
  1505.                     OTMemmove(&magic, &icmpHeader->data[0], 4);        // dst, src, nbytes
  1506.                     if (magic == kMagic) {
  1507.                         OTMemmove(&gFlakePercent, &icmpHeader->data[4], 2);
  1508.                         OTMemmove(&gFlakeLatency, &icmpHeader->data[6], 2);
  1509.                         dprintf("\nFlakeWay drop %d, delay %d", gFlakePercent, gFlakeLatency);
  1510.                     }
  1511.                 }
  1512.                 break;
  1513.  
  1514.             default:
  1515.                 // no port information available
  1516.                 filterData->sourcePorts.lo = 0;
  1517.                 filterData->destPorts.lo = 0;
  1518.                 // process through filter table
  1519. //                result = FilterDatagram(gFilterTable, filterData);
  1520.                 break;                
  1521.         }
  1522.     } while (false);
  1523.     
  1524.     return result;
  1525. }
  1526.  
  1527. #pragma mark • Macintosh Install Info •
  1528.  
  1529. /* ------------------------------------------------------------------------
  1530.  
  1531.     THESE FUNCTIONS AND DATA STRUCTURES ARE SPECIFIC TO THE MACINTOSH IMPLEMENTATION
  1532.     OF STREAMS. THESE ROUTINES WOULD NOT EXIST IN OTHER STREAMS ENVIRONMENTS.
  1533.     
  1534.     WHEN PORTING OTHER STREAMS CODE TO THE MACINTOSH, THESE ROUTINES AND DATA
  1535.     STRUCTURES MUST BE ADDED.
  1536.  
  1537.   ------------------------------------------------------------------------ */
  1538. install_info* GetOTProxymInstallInfo();
  1539. Boolean    InitProxymStreamModule(void* cookie);
  1540. void    TerminateProxymStreamModule();
  1541.  
  1542. /*******************************************************************************
  1543. ** install_info structure, and the GetInstallInfo function
  1544. **
  1545. ** This is the structure that tells Open Transport about your module. OT calls
  1546. ** your "GetInstallInfo" function to get this information.
  1547. **
  1548. ********************************************************************************/
  1549.     
  1550. install_info* GetOTProxymInstallInfo()
  1551. {
  1552.     return &proxymInstallInfo;
  1553. }
  1554.  
  1555. /*******************************************************************************
  1556. ** This is the function that will be called the first time that this code
  1557. ** is loaded.  It is guaranteed that this function is call at SystemTask time
  1558. ** on the Macintosh.
  1559. ********************************************************************************/
  1560.  
  1561. Boolean InitProxymStreamModule(void* cookie)
  1562. {
  1563.     /* Do any machine specific initialization stuff you need to */;
  1564.     gProxymListHead = NULL;
  1565.     proxymRefCountAdjusted    = false;
  1566.     //dprintf("\nInitProxymStreamModule");
  1567.     return true;
  1568. }
  1569.  
  1570. //    This function will be called when Open Transport removes the last
  1571. //    instance of a module or driver from the system.
  1572. void    TerminateProxymStreamModule()
  1573. {
  1574. }
  1575.  
  1576. // ===========================================================================
  1577.  
  1578. #pragma mark -
  1579. #pragma mark ••• Proxy STREAMS Driver •••
  1580. #pragma mark • module structure & procedures •
  1581.  
  1582.  
  1583. /*******************************************************************************
  1584. ** Open routine
  1585. ********************************************************************************/
  1586.     
  1587.     typedef struct proxy_struct
  1588.     {
  1589.         UInt16            myError;
  1590.         UInt16            myState;
  1591.         mblk_t*            timerMessage;
  1592.         UInt32            timerSequenceNumber;
  1593.         UInt32            timerUnAckCount;
  1594.         Boolean            monitorIsOnFlag;
  1595.     } proxy_struct;
  1596.     
  1597. int proxy_open(queue_t* rdq, dev_t* devp, int flag, int sflag, cred_t* credp)
  1598. {
  1599.     int                err;
  1600.     proxy_struct*    myData;
  1601.  
  1602.     // adjust ref count so we don't unload until companion module is free
  1603.     if ( OTCompareAndSwap32(1, 2, &proxyInstallInfo.ref_count) )
  1604.         proxyRefCountAdjusted = true;
  1605.  
  1606.     err = mi_open_comm(&gProxyListHead, sizeof(proxy_struct),
  1607.                         rdq, devp, flag, sflag, credp);
  1608.     
  1609.     if (err == 0) {
  1610.         //     Set my state in my data structure
  1611.         myData = (proxy_struct*)rdq->q_ptr;
  1612.         myData->myState            = TS_UNBND;
  1613.         myData->timerMessage = nilp(mblk_t);
  1614.         myData->timerSequenceNumber = 0;
  1615.         myData->timerUnAckCount = 0;
  1616.         myData->monitorIsOnFlag = false;
  1617.     }
  1618.     
  1619.     // return result
  1620.     return err;
  1621. }
  1622.         
  1623.  
  1624. /*******************************************************************************
  1625. ** Close routine
  1626. ********************************************************************************/
  1627.  
  1628. int proxy_close(queue_t* rdq, int flags, cred_t* credP)
  1629. {
  1630.     int        err;
  1631.     proxy_struct*    myData = (proxy_struct*)rdq->q_ptr;
  1632.     
  1633.     // release our timer message if any
  1634.     //OTKernelPrintf( kOTPrintOnly, "proxy_close closing driver.\n");
  1635.     if (myData->monitorIsOnFlag) {
  1636.         myData->monitorIsOnFlag = false;
  1637.         //  if timerMessage is pending, cancel it
  1638.         if (myData->timerMessage) {
  1639.             mi_timer_free(myData->timerMessage);
  1640.             myData->timerMessage = nilp(mblk_t);
  1641.         }
  1642.     }
  1643.  
  1644.     err = mi_close_comm(&gProxyListHead, rdq);
  1645.  
  1646.     // adjust ref count so we don't unload until companion module is free
  1647.     if (proxymInstallInfo.ref_count <= 1) {        // if done with companion
  1648.         // if I'm done, and my ref_count was adjusted,
  1649.         // decrement my ref_count so it can go to zero and
  1650.         if (proxyRefCountAdjusted) {
  1651.             if ( OTCompareAndSwap32(2, 1, &proxyInstallInfo.ref_count) ) {
  1652.                 proxymInstallInfo.ref_count = 0;    // set companion to zero ???
  1653.                 proxyRefCountAdjusted = false;
  1654.             }
  1655.         }
  1656.     }
  1657.     
  1658.     // return result
  1659.     return err;
  1660. }
  1661.  
  1662. /*******************************************************************************
  1663. ** Write-side put routine
  1664. ********************************************************************************/
  1665.  
  1666. int proxy_wput(queue_t* q, mblk_t* mp)
  1667. {
  1668.     Boolean result;
  1669.     UInt8    index;
  1670.     /*
  1671.      * Process the incoming message from the client
  1672.      */
  1673.     switch (mp->b_datap->db_type)
  1674.     {
  1675.         /*
  1676.          * Process a signal message - Under Open Transport, this is normally
  1677.          * a timer message.  If not a timer message for myself, pass it on.
  1678.          */
  1679.         case M_PCSIG:
  1680.             break;
  1681.         /*
  1682.          * Undocumented message type - just pass it on.
  1683.          */
  1684.         case M_HPDATA:
  1685.             break;
  1686.         /*
  1687.          * You will get one of these if you use M_COPYIN.  If it's not for
  1688.          * yourself, pass it on.
  1689.          */
  1690.         case M_IOCDATA:
  1691.             break;
  1692.         /*
  1693.          * These are messages for future expansion.  If not understood,
  1694.          * pass them on
  1695.          */
  1696.         case M_PCRSE:
  1697.         case M_RSE:
  1698.             break;
  1699.             
  1700.         /*
  1701.          * Request to flush queues.
  1702.          * Since we're a driver, we have to do a little more work
  1703.          */
  1704.         case M_FLUSH:
  1705.             if ( mp->b_rptr[0] & FLUSHW)
  1706.             {
  1707.                 if ( (mp->b_rptr[0] & FLUSHBAND) && mp->b_wptr - mp->b_rptr == 2 )
  1708.                     flushband(q, mp->b_rptr[1], FLUSHALL);
  1709.                 else
  1710.                     flushq(q, FLUSHALL);
  1711.             }
  1712.             if ( mp->b_rptr[0] & FLUSHR )
  1713.             {
  1714.                 if ( (mp->b_rptr[0] & FLUSHBAND) && mp->b_wptr - mp->b_rptr == 2 )
  1715.                     flushband(RD(q), mp->b_rptr[1], FLUSHALL);
  1716.                 else
  1717.                     flushq(RD(q), FLUSHALL);
  1718.                 mp->b_rptr[0] &= ~FLUSHW;
  1719.                 qreply(q, mp);
  1720.                 return 0;
  1721.             }
  1722.             break;
  1723.             
  1724.         /*
  1725.          * These messages are rarely uses, but you may need to process them.
  1726.          */
  1727.         case M_STOP:
  1728.         case M_START:
  1729.         case M_STOPI:
  1730.         case M_STARTI:
  1731.         case M_READ:
  1732.         case M_BREAK:
  1733.         case M_DELAY:
  1734.         case M_CTL:
  1735.             break;
  1736.             
  1737.         //    Here, we process any IOCTLs that we might support.
  1738.         case M_IOCTL:
  1739.         {
  1740.             struct iocblk* iocp = (struct iocblk*)mp->b_rptr;
  1741.             //OTKernelPrintf( kOTPrintOnly, "Entering wput IOCTL, ioc_cmd: %x.\n", iocp->ioc_cmd);
  1742.             proxy_struct*    myData = (proxy_struct*)q->q_ptr;
  1743.             
  1744.             switch ( iocp->ioc_cmd )
  1745.             {
  1746.                 case I_MonitorOn:
  1747.                     //    IOCTL requesting Monitor events
  1748.                                         
  1749.                     // Acknowledge client is handling events
  1750.                     myData->timerUnAckCount = 0;    // reset unacknowledged counter
  1751.                     
  1752.                     // Check if companion stream module has been configured
  1753.                     if (proxymInstallInfo.ref_count == 0) {
  1754.                         // companion module has not been configured, nothing to monitor.
  1755.                         // respond with M_IOCACK, monitor pending
  1756.                         mp->b_datap->db_type = M_IOCACK;    // set message type
  1757.                         iocp->ioc_error = 0;
  1758.                         iocp->ioc_count = 0;
  1759.                         iocp->ioc_rval = I_MonitorPending;
  1760.                         qreply(q, mp);
  1761.                         return 0;
  1762.                     }
  1763.                     
  1764.                     // If monitoring is not already turned on
  1765.                     if ( !myData->monitorIsOnFlag ) {
  1766.                                         
  1767.                         //    set state to generate events
  1768.                         //OTKernelPrintf( kOTPrintOnly, "Proxy IOCTL: I_SetMonitorOn.\n");
  1769.                         myData->monitorIsOnFlag = true;
  1770.                         
  1771.                         // create a new timer message
  1772.                         // try to allocate a timer message (q, size)
  1773.                         myData->timerMessage = mi_timer_alloc(RD(q), kTimerSize);
  1774.                         //  schedule message
  1775.                         if (myData->timerMessage) {
  1776.                             // re-initialize stat counters
  1777.                             proxy_GetTimedStat(q, nil, nil, nil);
  1778.                             // schedule for delay milliseconds
  1779.                             mi_timer(myData->timerMessage, kTimerDelay);
  1780.                         }
  1781.                     }
  1782.                                         
  1783.                     // respond with M_IOCACK
  1784.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  1785.                     iocp->ioc_error = 0;
  1786.                     iocp->ioc_count = 0;
  1787.                     iocp->ioc_rval = I_MonitorStart;
  1788.                     qreply(q, mp);
  1789.                     return 0;
  1790.                 case I_MonitorOff:
  1791.                     //    IOCTL to turn off Monitor events
  1792.                     //    set state to turn off events
  1793.                     if (myData->monitorIsOnFlag) {
  1794.                         myData->monitorIsOnFlag = false;
  1795.                         //  if timerMessage is pending, cancel it
  1796.                         if (myData->timerMessage) {
  1797.                             mi_timer_free(myData->timerMessage);
  1798.                             myData->timerMessage = nilp(mblk_t);
  1799.                         }
  1800.                     }
  1801.                     // respond with M_IOCACK
  1802.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  1803.                     iocp->ioc_error = 0;
  1804.                     iocp->ioc_count = 0;
  1805.                     iocp->ioc_rval = I_MonitorPause;
  1806.                     qreply(q, mp);
  1807.                     return 0;
  1808.                 
  1809.                 case I_SetMonitorName:
  1810.                     //    IOCTL to set Monitor Port Name
  1811.                     {
  1812.                         mblk_t*             mp2;
  1813.                         proxy_name_t*        proxyParam;                        
  1814.                         
  1815.                         // get Continued message block with IOCTL data
  1816.                             // is there any data?
  1817.                         if (iocp->ioc_count >= sizeof(proxy_name_t)) {
  1818.                             mp2 = mp->b_cont;
  1819.                             proxyParam = (proxy_name_t*)mp2->b_rptr;
  1820.                             // save hashed interface name
  1821.                             gMonitorName = proxyParam->portNameHash;                    
  1822.                             //OTKernelPrintf( kOTPrintThenStop, "IOCTL Set on demand name, param: %x \n", gInterfaceName);
  1823.                         }
  1824.                     }
  1825.                     // respond with M_IOCACK
  1826.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  1827.                     iocp->ioc_error = 0;
  1828.                     iocp->ioc_count = 0;
  1829.                     iocp->ioc_rval = kProxyNoError;
  1830.                     qreply(q, mp);
  1831.                     return 0;
  1832.  
  1833.                 case I_SetPortName:
  1834.                     //    IOCTL to set Port Name for NAT
  1835.                     {
  1836.                         mblk_t*             mp2;
  1837.                         proxy_name_t*        proxyParam;
  1838. //                        UInt8                i;
  1839.                         
  1840.                         result = false;
  1841.                         // get Continued message block with IOCTL data
  1842.                             // is there any data?
  1843.                         if (iocp->ioc_count >= sizeof(proxy_name_t)) {
  1844.                             mp2 = mp->b_cont;
  1845.                             proxyParam = (proxy_name_t*)mp2->b_rptr;
  1846.                             // look for an available NAT table or already assigned
  1847. /*
  1848.                             for (i=0; i<kNatNumDim; i++) {
  1849.                                 if ((GetPortName(gNatTable[i]) == 0) ||
  1850.                                     (GetPortName(gNatTable[i]) == proxyParam->portNameHash)) {
  1851.                                     // Init the NAT table to get ready for use
  1852. //                                    InitTable(gNatTable[i]);
  1853.                                     // set port name to indicate table in use
  1854. //                                    SetPortName(gNatTable[i], proxyParam->portNameHash);
  1855.                                     result = true;
  1856.                                     break;
  1857.                                 }
  1858.                             }
  1859. */
  1860.                             // save hashed interface name
  1861. //                            gInterfaceName = HashName(proxyInterfaceName->name);                        
  1862.                             //OTKernelPrintf( kOTPrintThenStop, "IOCTL Set interface name, param: %x \n", gInterfaceName);
  1863.                         }
  1864.                     }
  1865.                     // respond with M_IOCACK
  1866.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  1867.                     iocp->ioc_error = 0;
  1868.                     iocp->ioc_count = 0;
  1869.                     iocp->ioc_rval = kProxyNoError;
  1870.                     if (!result) iocp->ioc_rval = kProxyTableError;
  1871.                     qreply(q, mp);
  1872.                     return 0;
  1873.                 case I_GetPortNames:
  1874.                     //    IOCTL to get Port Names for NAT
  1875.                     {
  1876.                         mblk_t*             mp2;
  1877.                         proxy_names_t*        proxyParam;
  1878. //                        UInt8                i;
  1879.                         
  1880.                         result = false;
  1881.                         // get Continued message block with IOCTL data
  1882.                             // is there any data?
  1883.                         if (iocp->ioc_count >= sizeof(proxy_names_t)) {
  1884.                             mp2 = mp->b_cont;
  1885.                             proxyParam = (proxy_names_t*)mp2->b_rptr;
  1886.                             // look for an available NAT table
  1887. //                            for (i=0; i<kNatNumDim; i++) {
  1888. //                                proxyParam->NatPortName[i] = GetPortName(gNatTable[i]);
  1889. //                                proxyParam->NatIPAddr[i] = GetNatNetwork(gNatTable[i])->address;
  1890. //                            }
  1891.                             result = true;
  1892.                         }
  1893.                     }
  1894.                     // respond with M_IOCACK
  1895.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  1896.                     iocp->ioc_error = 0;
  1897.                     //iocp->ioc_count = 0;    // leave as passed in
  1898.                     iocp->ioc_rval = kProxyNoError;
  1899.                     if (!result) iocp->ioc_rval = kProxyTableError;
  1900.                     qreply(q, mp);
  1901.                     return 0;
  1902.                 case I_SetApparentAddress:
  1903.                     //    IOCTL to set Apparent Address for NAT
  1904.                     {
  1905.                         FilterTableData_t*  filterData;
  1906.                         mblk_t*             mp2;
  1907.                         proxy_network_t*    proxyParam;
  1908. //                        UInt8                i;                    
  1909.                         
  1910.                         // get Continued message block with IOCTL data
  1911.                             // is there any data?
  1912.                         if (iocp->ioc_count >= sizeof(proxy_network_t)) {
  1913.                             mp2 = mp->b_cont;
  1914.                             proxyParam = (proxy_network_t*)mp2->b_rptr;
  1915.                             // find corresponding NAT table
  1916. //                            for (i=0; i<kNatNumDim; i++) {
  1917. //                                if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  1918. //                                    // set address
  1919. //                                    SetNatNetwork(gNatTable[i], &proxyParam->net);
  1920. //                                    break;
  1921. //                                }
  1922. //                            }
  1923.                             // save as dynamic address in filter table
  1924.                             filterData = (FilterTableData_t*)&gFilterTable[0];
  1925.                             filterData->ipAddress = proxyParam->net.address;                        
  1926.                             //OTKernelPrintf( kOTPrintThenStop, "IOCTL Set Apparent Address, param: %x \n", proxyParam->array[0]);
  1927.                         }
  1928.                     }
  1929.                     // respond with M_IOCACK
  1930.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  1931.                     iocp->ioc_error = 0;
  1932.                     iocp->ioc_count = 0;
  1933.                     iocp->ioc_rval = kProxyNoError;
  1934.                     qreply(q, mp);
  1935.                     return 0;
  1936.                 case I_SetExposedHost:
  1937.                     //    IOCTL to set Exposed Host address for NAT
  1938.                     {
  1939.                         mblk_t*             mp2;
  1940.                         proxy_network_t*    proxyParam;
  1941. //                        UInt8                i;                    
  1942.                         
  1943.                         // get Continued message block with IOCTL data
  1944.                             // is there any data?
  1945.                         if (iocp->ioc_count >= sizeof(proxy_network_t)) {
  1946.                             mp2 = mp->b_cont;
  1947.                             proxyParam = (proxy_network_t*)mp2->b_rptr;
  1948.                             // find corresponding NAT table
  1949. //                            for (i=0; i<kNatNumDim; i++) {
  1950. //                                if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  1951. //                                    // set address
  1952. //                                    SetExposedHost(gNatTable[i], proxyParam->net.address);
  1953. //                                    break;
  1954. //                                }
  1955. //                            }
  1956.                         }
  1957.                     }
  1958.                     // respond with M_IOCACK
  1959.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  1960.                     iocp->ioc_error = 0;
  1961.                     iocp->ioc_count = 0;
  1962.                     iocp->ioc_rval = kProxyNoError;
  1963.                     qreply(q, mp);
  1964.                     return 0;
  1965.                 case I_SetActualNetwork:
  1966.                     //    IOCTL to set Actual Network that should not be translated
  1967.                     {
  1968.                         mblk_t*             mp2;
  1969.                         proxy_network_t*    proxyParam;
  1970. //                        UInt8                i;
  1971.                         
  1972.                         // get Continued message block with IOCTL data
  1973.                             // is there any data?
  1974.                         if (iocp->ioc_count >= sizeof(proxy_network_t)) {
  1975.                             mp2 = mp->b_cont;
  1976.                             proxyParam = (proxy_network_t*)mp2->b_rptr;
  1977.                             // find corresponding NAT table
  1978. //                            for (i=0; i<kNatNumDim; i++) {
  1979. //                                if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  1980. //                                    // set actual network
  1981. //                                    SetActualNetwork(gNatTable[i], &proxyParam->net);
  1982. //                                    break;
  1983. //                                }
  1984. //                            }
  1985.                             // setup to access NAT parameters
  1986. //                            data = (tableData_t*)&gNatTable[0];
  1987. //                            data->actualNetwork.address = proxyParam->address;
  1988. //                            data->actualNetwork.mask = proxyParam->mask;
  1989.                             //OTKernelPrintf( kOTPrintOnly,    "IOCTL Set Actual Network: %x \n", proxyParam->address);
  1990.                         }
  1991.                     }
  1992.                     // respond with M_IOCACK
  1993.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  1994.                     iocp->ioc_error = 0;
  1995.                     iocp->ioc_count = 0;
  1996.                     iocp->ioc_rval = kProxyNoError;
  1997.                     qreply(q, mp);
  1998.                     return 0;
  1999.                 case I_NatOn:
  2000.                     // turn NAT on
  2001.                     {
  2002.                         mblk_t*             mp2;
  2003.                         proxy_name_t*        proxyParam;
  2004. //                        UInt8                i;
  2005.                         
  2006.                         result = false;
  2007.                         // get Continued message block with IOCTL data
  2008.                             // is there any data?
  2009.                         if (iocp->ioc_count >= sizeof(proxy_name_t)) {
  2010.                             mp2 = mp->b_cont;
  2011.                             proxyParam = (proxy_name_t*)mp2->b_rptr;
  2012.                             // look for corresponding NAT table
  2013. //                            for (i=0; i<kNatNumDim; i++) {
  2014. //                                if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  2015. //                                    // enable NAT for this table
  2016. //                                    SetNatOn(gNatTable[i], true);
  2017. //                                    result = true;
  2018. //                                    break;
  2019. //                                }
  2020. //                            }
  2021.                         }
  2022.                     }
  2023.                     // respond with M_IOCACK
  2024.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2025.                     iocp->ioc_error = 0;
  2026.                     iocp->ioc_count = 0;
  2027.                     iocp->ioc_rval = kProxyNoError;
  2028.                     if (!result) iocp->ioc_rval = kProxyTableError;
  2029.                     qreply(q, mp);
  2030.                     return 0;
  2031.                 case I_NatOff:
  2032.                     //    IOCTL to turn NAT off
  2033.                     {
  2034.                         mblk_t*             mp2;
  2035.                         proxy_name_t*        proxyParam;
  2036. //                        UInt8                i;
  2037.                         
  2038.                         result = false;
  2039.                         // get Continued message block with IOCTL data
  2040.                             // is there any data?
  2041.                         if (iocp->ioc_count >= sizeof(proxy_name_t)) {
  2042.                             mp2 = mp->b_cont;
  2043.                             proxyParam = (proxy_name_t*)mp2->b_rptr;
  2044.                             // look for corresponding NAT table
  2045. /*
  2046.                             for (i=0; i<kNatNumDim; i++) {
  2047.                                 if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  2048.                                     // disable NAT for this table
  2049. //                                    SetNatOn(gNatTable[i], false);
  2050.                                     // set port name to indicate table is available
  2051. //                                    SetPortName(gNatTable[i], 0);
  2052.                                     // Init the NAT table to get ready for next time
  2053.                                     //InitTable(gNatTable[i], (UInt32)sizeof(gNatTable[i]));
  2054.                                     result = true;
  2055.                                     break;
  2056.                                 }
  2057.                             }
  2058. */
  2059.                         }
  2060.                     }
  2061.                     // respond with M_IOCACK
  2062.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2063.                     iocp->ioc_error = 0;
  2064.                     iocp->ioc_count = 0;
  2065.                     iocp->ioc_rval = kProxyNoError;
  2066.                     if (!result) iocp->ioc_rval = kProxyTableError;
  2067.                     qreply(q, mp);
  2068.                     return 0;
  2069.                 case I_LocalNatOn:
  2070.                     //    IOCTL to turn Local NAT on
  2071.                     if (!gIsLocalNatOn) {
  2072.                         gIsLocalNatOn = true;
  2073.                     }
  2074.                     // respond with M_IOCACK
  2075.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2076.                     iocp->ioc_error = 0;
  2077.                     iocp->ioc_count = 0;
  2078.                     iocp->ioc_rval = kProxyNoError;
  2079.                     qreply(q, mp);
  2080.                     return 0;
  2081.                 case I_LocalNatOff:
  2082.                     //    IOCTL to turn Local NAT off
  2083.                     if (gIsLocalNatOn) {
  2084.                         gIsLocalNatOn = false;
  2085.                     }
  2086.                     // respond with M_IOCACK
  2087.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2088.                     iocp->ioc_error = 0;
  2089.                     iocp->ioc_count = 0;
  2090.                     iocp->ioc_rval = kProxyNoError;
  2091.                     qreply(q, mp);
  2092.                     return 0;
  2093.                 case I_TRCableModem:
  2094.                     //    IOCTL to enable TRCableModem
  2095.                     if (!gIsTRCableModem) {
  2096.                         gIsTRCableModem = true;
  2097.                     }
  2098.                     // respond with M_IOCACK
  2099.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2100.                     iocp->ioc_error = 0;
  2101.                     iocp->ioc_count = 0;
  2102.                     iocp->ioc_rval = kProxyNoError;
  2103.                     qreply(q, mp);
  2104.                     return 0;
  2105.                 case I_TRCableModemOff:
  2106.                     //    IOCTL to disable TRCableModem
  2107.                     if (gIsTRCableModem) {
  2108.                         gIsTRCableModem = false;
  2109.                     }
  2110.                     // respond with M_IOCACK
  2111.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2112.                     iocp->ioc_error = 0;
  2113.                     iocp->ioc_count = 0;
  2114.                     iocp->ioc_rval = kProxyNoError;
  2115.                     qreply(q, mp);
  2116.                     return 0;
  2117.                 case I_DNSForwardingOn:
  2118.                     //    IOCTL to enable DNSForarding
  2119.                     if (!gIsDNSForwarding) {
  2120.                         gIsDNSForwarding = true;
  2121.                     }
  2122.                     // respond with M_IOCACK
  2123.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2124.                     iocp->ioc_error = 0;
  2125.                     iocp->ioc_count = 0;
  2126.                     iocp->ioc_rval = kProxyNoError;
  2127.                     qreply(q, mp);
  2128.                     return 0;
  2129.                 case I_DNSForwardingOff:
  2130.                     //    IOCTL to disable DNSForarding
  2131.                     if (gIsDNSForwarding) {
  2132.                         gIsDNSForwarding = false;
  2133.                     }
  2134.                     // respond with M_IOCACK
  2135.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2136.                     iocp->ioc_error = 0;
  2137.                     iocp->ioc_count = 0;
  2138.                     iocp->ioc_rval = kProxyNoError;
  2139.                     qreply(q, mp);
  2140.                     return 0;
  2141.                 case I_ClampMSS:
  2142.                     // IOCTL to set TCP MSS clamp for proxy interface
  2143.                     {
  2144.                         mblk_t*             mp2;
  2145.                         proxy_mss_t*        proxyParam;
  2146. //                        UInt8                i;
  2147.                         
  2148.                         // get Continued message block with IOCTL data
  2149.                             // is there any data?
  2150.                         if (iocp->ioc_count >= sizeof(proxy_mss_t)) {
  2151.                             mp2 = mp->b_cont;
  2152.                             proxyParam = (proxy_mss_t*)mp2->b_rptr;
  2153.                             // look for corresponding NAT table
  2154. /*
  2155.                             for (i=0; i<kNatNumDim; i++) {
  2156.                                 if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  2157.                                     // set MSS Clamp for this table
  2158. //                                    SetMSSClamp(gNatTable[i], (UInt16)proxyParam->mssClamp);
  2159.                                     break;
  2160.                                 }
  2161.                             }
  2162. */
  2163.                         }
  2164.                     }
  2165.                     // respond with M_IOCACK
  2166.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2167.                     iocp->ioc_error = 0;
  2168.                     //iocp->ioc_count = 0;        // leave as sent        
  2169.                     iocp->ioc_rval = kProxyNoError;
  2170.                     qreply(q, mp);
  2171.                     return 0;
  2172.                 case I_AgeNatTable:
  2173.                     {
  2174.                         mblk_t*             mp2;
  2175.                         proxy_age_t*        proxyParam;
  2176.                         UInt16                timeOut;
  2177. //                        UInt16                count;
  2178. //                        UInt8                i;
  2179.                         
  2180.                         timeOut = kTimeOutTCP;    // initialize default
  2181.                         // get Continued message block with IOCTL data
  2182.                             // is there any data?
  2183.                         if (iocp->ioc_count >= sizeof(proxy_age_t)) {
  2184.                             mp2 = mp->b_cont;
  2185.                             proxyParam = (proxy_age_t*)mp2->b_rptr;
  2186.                             // Age table with timeout parameter                            
  2187.                             timeOut = proxyParam->age;
  2188. /*
  2189.                             // look for corresponding NAT table
  2190.                             for (i=0; i<kNatNumDim; i++) {
  2191.                                 if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  2192.                                     // enable NAT for this table
  2193. //                                    count = AgeTable(gNatTable[i], timeOut);
  2194.                                     // return resulting number of entries
  2195.                                     proxyParam->age = count;
  2196.                                     result = true;
  2197.                                     break;
  2198.                                 }
  2199.                             }
  2200. */
  2201.                         }
  2202.                     }
  2203.                     // respond with M_IOCACK
  2204.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2205.                     iocp->ioc_error = 0;
  2206.                     //iocp->ioc_count = 0;        // leave as sent        
  2207.                     iocp->ioc_rval = kProxyNoError;
  2208.                     qreply(q, mp);
  2209.                     return 0;
  2210.                 
  2211.                 case I_SetOnDemandName:
  2212.                     //    IOCTL to set OnDemand Interface Name
  2213.                     {
  2214.                         mblk_t*             mp2;
  2215.                         proxy_name_t*        proxyParam;                        
  2216.                         
  2217.                         // get Continued message block with IOCTL data
  2218.                             // is there any data?
  2219.                         if (iocp->ioc_count >= sizeof(proxy_name_t)) {
  2220.                             mp2 = mp->b_cont;
  2221.                             proxyParam = (proxy_name_t*)mp2->b_rptr;
  2222.                             // save hashed interface name
  2223.                             gOnDemandName = proxyParam->portNameHash;                    
  2224.                             //OTKernelPrintf( kOTPrintThenStop, "IOCTL Set on demand name, param: %x \n", gInterfaceName);
  2225.                         }
  2226.                     }
  2227.                     // respond with M_IOCACK
  2228.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2229.                     iocp->ioc_error = 0;
  2230.                     iocp->ioc_count = 0;
  2231.                     iocp->ioc_rval = kProxyNoError;
  2232.                     qreply(q, mp);
  2233.                     return 0;
  2234.                 
  2235.                 case I_OnDemandUp:
  2236.                     // IOCTL to indicate OnDemand is up
  2237.                     gIsOnDemandUp = true;
  2238.                     gIsOnDemandPending = false;            // reset connection needed
  2239.                     // respond with M_IOCACK
  2240.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2241.                     iocp->ioc_error = 0;
  2242.                     iocp->ioc_count = 0;
  2243.                     iocp->ioc_rval = kProxyNoError;
  2244.                     qreply(q, mp);
  2245.                     return 0;
  2246.  
  2247.                 case I_OnDemandDown:
  2248.                     // IOCTL to indicate OnDemand is down
  2249.                     gIsOnDemandPending = false;    // reset connection needed
  2250.                     gIsOnDemandUp = false;
  2251.                     // respond with M_IOCACK
  2252.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2253.                     iocp->ioc_error = 0;
  2254.                     iocp->ioc_count = 0;
  2255.                     iocp->ioc_rval = kProxyNoError;
  2256.                     qreply(q, mp);
  2257.                     return 0;
  2258.  
  2259.                 case I_OnDemandConnect:
  2260.                     // IOCTL to test if On Demand connection needed
  2261.                     {
  2262.                         mblk_t*             mp2;
  2263.                         NetNumber_t*            addressParam;                        
  2264.                         
  2265.                         // get Continued message block with IOCTL data
  2266.                             // is there any data?
  2267.                         if (iocp->ioc_count >= sizeof(proxy_network_t)) {
  2268.                             mp2 = mp->b_cont;
  2269.                             addressParam = (NetNumber_t*)mp2->b_rptr;
  2270.                             // return srcAddress of on demand traffic                            
  2271.                             addressParam->address = gOnDemandSrcAddress;
  2272.                             addressParam->mask = 0;                        
  2273.                         }
  2274.                     }
  2275.                     // respond with M_IOCACK
  2276.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2277.                     iocp->ioc_error = 0;
  2278.                     //iocp->ioc_count = 0;    // leave as sent
  2279.                     iocp->ioc_rval = kProxyNoError;
  2280.                     if (gIsOnDemandPending && (gIsOnDemandUp == false)) {
  2281.                         iocp->ioc_rval = kProxyOnDemand;
  2282.                     }
  2283.                     qreply(q, mp);
  2284.                     return 0;
  2285.  
  2286.                 // Access to NAT Table
  2287.                 case I_GetFullMap:
  2288.                     index = 0;        // default to first table
  2289.                     {
  2290.                         mblk_t*             mp2;
  2291.                         proxy_name_t*        proxyParam;
  2292. //                        UInt8                i;
  2293.  
  2294.                         // get Continued message block with IOCTL data
  2295.                             // is there any data?
  2296.                         if (iocp->ioc_count >= sizeof(proxy_name_t)) {
  2297.                             mp2 = mp->b_cont;
  2298.                             proxyParam = (proxy_name_t*)mp2->b_rptr;
  2299.                             // look for corresponding NAT table
  2300. /*
  2301.                             for (i=0; i<kNatNumDim; i++) {
  2302.                                 if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  2303.                                     // remember which NAT table
  2304.                                     index = i;
  2305.                                     break;
  2306.                                 }
  2307.                             }
  2308. */
  2309.                         }
  2310.                     }
  2311.                     // respond with M_IOCACK
  2312.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2313.                     iocp->ioc_error = 0;
  2314.                     iocp->ioc_count = 0;
  2315.                     iocp->ioc_rval = kProxyNoError;
  2316.                     qreply(q, mp);
  2317.                     // send requested data
  2318. //                    result = proxy_SendNat(gNatTable[index], RD(q), kFullMap);
  2319.                     return 0;
  2320.                 case I_GetStaticMap:
  2321.                     index = 0;        // default to first table
  2322.                     {
  2323.                         mblk_t*             mp2;
  2324.                         proxy_name_t*        proxyParam;
  2325. //                        UInt8                i;
  2326.  
  2327.                         // get Continued message block with IOCTL data
  2328.                             // is there any data?
  2329.                         if (iocp->ioc_count >= sizeof(proxy_name_t)) {
  2330.                             mp2 = mp->b_cont;
  2331.                             proxyParam = (proxy_name_t*)mp2->b_rptr;
  2332.  
  2333.                             // look for corresponding NAT table
  2334. /*                            for (i=0; i<kNatNumDim; i++) {
  2335.                                 if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  2336.                                     // remember which NAT table
  2337.                                     index = i;
  2338.                                     break;
  2339.                                 }
  2340.                             }
  2341. */                            
  2342.                         }
  2343.                     }
  2344.                     // respond with M_IOCACK
  2345.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2346.                     iocp->ioc_error = 0;
  2347.                     iocp->ioc_count = 0;
  2348.                     iocp->ioc_rval = kProxyNoError;
  2349.                     qreply(q, mp);
  2350.                     // send requested data
  2351. //                    result = proxy_SendNat(gNatTable[index], RD(q), kStaticMap);
  2352.                     return 0;
  2353.                 case I_AddMapEntry:
  2354.                     {
  2355.                         mblk_t*             mp2;
  2356.                         proxy_map_entry_t*    proxyParam;
  2357.                         translationEntry_t    tableEntry;
  2358. //                        UInt8                i;
  2359.                         index = 0;        // default to first table
  2360.                         // get Continued message block with IOCTL data
  2361.                             // is there any data?
  2362.                         if (iocp->ioc_count >= sizeof(proxy_map_entry_t)) {
  2363.                             mp2 = mp->b_cont;
  2364.                             proxyParam = (proxy_map_entry_t*)mp2->b_rptr;
  2365.                             // look for corresponding NAT table
  2366. /*
  2367.                             for (i=0; i<kNatNumDim; i++) {
  2368.                                 if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  2369.                                     // remember which NAT table
  2370.                                     index = i;
  2371.                                     break;
  2372.                                 }
  2373.                             }
  2374. */
  2375.                         }
  2376.                         // load search info
  2377.                         bzero(&tableEntry, sizeof(translationEntry_t));
  2378.                         tableEntry.apparent = proxyParam->mapEntry.apparent;
  2379.                         tableEntry.portRange= proxyParam->mapEntry.portRange;
  2380.                         tableEntry.actual    = proxyParam->mapEntry.actual;
  2381.                         tableEntry.protocol    = proxyParam->mapEntry.protocol;
  2382.                         tableEntry.age        = proxyParam->mapEntry.age;
  2383.                         tableEntry.flags    = proxyParam->mapEntry.flags;
  2384.                         // find table entry if any
  2385. //                        tableEntry.entryID = FindEntry(gNatTable[index], &tableEntry);
  2386.                         // add to table
  2387. //                        result = WriteEntry(gNatTable[index], &tableEntry);
  2388.                     }
  2389.                     // respond with M_IOCACK
  2390.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2391.                     iocp->ioc_error = 0;
  2392.                     iocp->ioc_count = 0;
  2393.                     iocp->ioc_rval = kProxyNoError;
  2394.                     if (!result) iocp->ioc_rval = kProxyAddError;
  2395.                     qreply(q, mp);
  2396.                     return 0;
  2397.                 case I_DelMapEntry:
  2398.                     {
  2399.                         mblk_t*             mp2;
  2400.                         proxy_map_entry_t*    proxyParam;
  2401.                         translationEntry_t    tableEntry;
  2402.                         UInt16                entryID;
  2403.                         UInt16                prev;
  2404. //                        UInt8                i;
  2405.                         index = 0;        // default to first table
  2406.                         result = false;
  2407.                         // get Continued message block with IOCTL data
  2408.                             // is there any data?
  2409.                         if (iocp->ioc_count >= sizeof(proxy_map_entry_t)) {
  2410.                             mp2 = mp->b_cont;
  2411.                             proxyParam = (proxy_map_entry_t*)mp2->b_rptr;
  2412. /*
  2413.                             // look for corresponding NAT table
  2414.                             for (i=0; i<kNatNumDim; i++) {
  2415.                                 if (proxyParam->portNameHash == GetPortName(gNatTable[i])) {
  2416.                                     // remember which NAT table
  2417.                                     index = i;
  2418.                                     break;
  2419.                                 }
  2420.                             }
  2421. */
  2422.                         }
  2423.                         // load search info
  2424.                         tableEntry.apparent = proxyParam->mapEntry.apparent;
  2425.                         tableEntry.portRange= proxyParam->mapEntry.portRange;
  2426.                         tableEntry.actual    = proxyParam->mapEntry.actual;
  2427.                         tableEntry.protocol    = proxyParam->mapEntry.protocol;
  2428.                         tableEntry.age        = proxyParam->mapEntry.age;
  2429.                         tableEntry.flags    = proxyParam->mapEntry.flags;
  2430.                         // find table entry if any
  2431. //                        entryID = FindEntry(gNatTable[index], &tableEntry);
  2432.                         // try to delete it
  2433.                         prev = 0;
  2434.                         if (entryID != 0) {
  2435. //                            DeleteEntry(gNatTable[index], entryID, prev);
  2436.                             result = true;
  2437.                         } else result = false;
  2438.                     }
  2439.                     // respond with M_IOCACK
  2440.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2441.                     iocp->ioc_error = 0;
  2442.                     iocp->ioc_count = 0;
  2443.                     iocp->ioc_rval = kProxyNoError;
  2444.                     if (!result) iocp->ioc_rval = kProxyDelError;
  2445.                     qreply(q, mp);
  2446.                     return 0;
  2447.                 
  2448.                 // Access to filter table
  2449.                 case I_GetFilters:
  2450.                     // respond with M_IOCACK
  2451.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2452.                     iocp->ioc_error = 0;
  2453.                     iocp->ioc_count = 0;
  2454.                     iocp->ioc_rval = kProxyNoError;
  2455.                     qreply(q, mp);
  2456.                     // send requested data
  2457. //                    proxy_SendFilters(RD(q));
  2458.                     return 0;
  2459.                 case I_AddFilterEntry:
  2460.                     {
  2461.                         mblk_t*             mp2;
  2462.                         FilterEntry_t*        filterEntry;
  2463.                         // get Continued message block with IOCTL data
  2464.                             // is there any data?
  2465.                         if (iocp->ioc_count >= sizeof(FilterEntry_t)) {
  2466.                             mp2 = mp->b_cont;
  2467.                             filterEntry = (FilterEntry_t*)mp2->b_rptr;
  2468.                             // add to table
  2469. //                            result = WriteFilterEntry(gFilterTable, filterEntry);
  2470.                         }
  2471.                     }
  2472.                     // respond with M_IOCACK
  2473.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2474.                     iocp->ioc_error = 0;
  2475.                     iocp->ioc_count = 0;
  2476.                     iocp->ioc_rval = kProxyNoError;
  2477.                     if (!result) iocp->ioc_rval = kProxyAddError;
  2478.                     qreply(q, mp);
  2479.                     return 0;
  2480.                 case I_DelFilterEntry:
  2481.                     {
  2482.                         mblk_t*             mp2;
  2483.                         FilterEntry_t*        filterEntry;
  2484.                         UInt16                index;
  2485.                         UInt16                prev;
  2486.                         // get Continued message block with IOCTL data
  2487.                             // is there any data?
  2488.                         if (iocp->ioc_count >= sizeof(FilterEntry_t)) {
  2489.                             mp2 = mp->b_cont;
  2490.                             filterEntry = (FilterEntry_t*)mp2->b_rptr;
  2491.                             // find table entry if any
  2492. //                            index = FindFilterEntry(gFilterTable, filterEntry);
  2493.                             // try to delete it
  2494.                             prev = 0;
  2495.                             if (index != 0) {
  2496. //                                DeleteFilterEntry(gFilterTable, index, prev);
  2497.                                 result = true;
  2498.                             } else result = false;
  2499.                         }
  2500.                     }
  2501.                     // respond with M_IOCACK
  2502.                     mp->b_datap->db_type = M_IOCACK;    // set message type
  2503.                     iocp->ioc_error = 0;
  2504.                     iocp->ioc_count = 0;
  2505.                     iocp->ioc_rval = kProxyNoError;
  2506.                     if (!result) iocp->ioc_rval = kProxyDelError;
  2507.                     qreply(q, mp);
  2508.                     return 0;
  2509.  
  2510.                 default:
  2511.                     // As a driver, it is our responsibility to NAK any IOCTL we receive
  2512.                     // that we don't understand.  If we were a module, we would just pass it on.
  2513.                     iocp->ioc_error            = EINVAL;
  2514.                     iocp->ioc_count            = 0;
  2515.                     mp->b_datap->db_type    = M_IOCNAK;
  2516.                     qreply(q, mp);
  2517.                     return 0;
  2518.             }
  2519.         }
  2520.         break;
  2521.         
  2522.         /*
  2523.          * Handle data coming from the client
  2524.          */
  2525.         case M_DATA:
  2526.             return proxy_wdata(q, mp);
  2527.         
  2528.         /*
  2529.          * Handle M_PROTO and M_PCPROTO requests coming from the client
  2530.          */
  2531.         case M_PROTO:
  2532.         case M_PCPROTO:
  2533.             return proxy_wproto(q, mp);
  2534.             
  2535.         /*
  2536.          * Should never see one of these messages. It is an invisible message
  2537.          * used by the streamhead.
  2538.          */
  2539.         case M_PASSFP:
  2540.             break;
  2541.             
  2542.         default:
  2543.             break;
  2544.     }
  2545.     // There's no one to pass it on to, so just free the message.
  2546. //    OTKernelPrintf( kOTPrintThenStop, "proxy_wput, unexpected db_type: %d.\n", mp->b_datap->db_type);
  2547.     freemsg(mp);
  2548.     return 0;
  2549. }
  2550.  
  2551. /*******************************************************************************
  2552. ** Read-side put routine
  2553. ********************************************************************************/
  2554.  
  2555. int proxy_rput(queue_t* q, mblk_t* mp)
  2556. {
  2557. //OTKernelPrintf( kOTPrintThenStop, "Entering proxy_rput, db_type: %d.\n", mp->b_datap->db_type);
  2558.     proxy_struct*    myData = (proxy_struct*)q->q_ptr;
  2559.     /*
  2560.      * Process the incoming message from a timer or any other
  2561.      * We're a driver, so there's no one below us.
  2562.      */
  2563.     switch (mp->b_datap->db_type)
  2564.     {
  2565.         /*
  2566.          * Miscellaneous messages - pass them on if you don't want them
  2567.          */
  2568.         case M_STOP:
  2569.         case M_START:
  2570.         case M_STOPI:
  2571.         case M_STARTI:
  2572.             break;
  2573.             
  2574.         /*
  2575.          * Just send these on up to the streamhead
  2576.          */
  2577.         case M_COPYIN:
  2578.         case M_COPYOUT:
  2579.         case M_ERROR:
  2580.         case M_HANGUP:
  2581.         case M_PCRSE:
  2582.             break;
  2583.         
  2584.         /*
  2585.          * If we send any IOCTLs downstream, look at the acks and 
  2586.          * nacks here to determine if these are ours.  If so, process
  2587.          * them.  Otherwise, just send them on upstream
  2588.          */
  2589.         case M_IOCACK:
  2590.         case M_IOCNAK:
  2591.             break;
  2592.         
  2593.         /*
  2594.          * If we ure any timers, process them here.  Otherwise, send
  2595.          * the signal upstream
  2596.          */
  2597.         case M_PCSIG:
  2598.             // record timer has been delivered, so we don't try to cancel it
  2599.             myData->timerMessage = nilp(mblk_t);
  2600.             // Test if message is valid
  2601.             if ( !mi_timer_valid(mp) ) return 0;    // If not valid, ignore it!
  2602.             mi_timer_free(mp);                        // free the message
  2603.             // Send timed stat message upstream if monitoring is turned on
  2604.             if ( myData->monitorIsOnFlag ) {
  2605.                 proxy_SendStats(q);
  2606. /*                
  2607.                 // Check if companion stream module is still configured
  2608.                 if (proxymInstallInfo.ref_count == 0) {
  2609.                     // companion module is no longer configured, nothing to monitor
  2610.                     // turn off monitoring
  2611.                     myData->monitorIsOnFlag = false;
  2612.                     return 0;
  2613.                 }
  2614. */
  2615.                 // try to allocate new timer message (q, size)
  2616.                 myData->timerMessage = mi_timer_alloc(q, kTimerSize);
  2617.                 //  schedule message
  2618.                 if (myData->timerMessage) mi_timer(myData->timerMessage, kTimerDelay);
  2619.                 else {
  2620.                     myData->monitorIsOnFlag = false;    // alloc failed, so monitoring is off
  2621.                     myData->timerSequenceNumber = 0;    // reset sequence numbers
  2622.                 }
  2623.             }
  2624.             return 0;
  2625.                 
  2626.         /*
  2627.          * Undocumented message type - send it on
  2628.          */
  2629.         case M_HPDATA:
  2630.             break;
  2631.             
  2632.             
  2633.         /*
  2634.          * Handle data coming from downstream
  2635.          */
  2636.         //case M_DATA:
  2637.         //    return proxy_rdata(q, mp);
  2638.         
  2639.         /*
  2640.          * Handle M_PROTO and M_PCPROTO requests coming from downstream
  2641.          */
  2642.         //case M_PROTO:
  2643.         //case M_PCPROTO:
  2644.         //    return proxy_rproto(q, mp);
  2645.             
  2646.         /*
  2647.          * Anything we don't understand - just pass it on
  2648.          */
  2649.         default:
  2650.             break;
  2651.     }
  2652. //    OTKernelPrintf( kOTPrintThenStop, "proxy_rput, unexpected db_type: %d.\n", mp->b_datap->db_type);
  2653.     putnext(q, mp);
  2654.     return 0;
  2655. }
  2656.  
  2657. #pragma mark • module support functions •
  2658.  
  2659.  
  2660. /*******************************************************************************
  2661. ** Write-side processing routines
  2662. ********************************************************************************/
  2663.  
  2664. int proxy_wdata(queue_t* q, mblk_t* mp)
  2665. {
  2666.     /*    ---------------------------------------------------------------------
  2667.         Here, we do whatever munging we're going to do on the client data,
  2668.         then send it on.
  2669.         Keep in mind that we call this routine from the proxy_wproto routine,
  2670.         so that the first block of the message might be an M_PROTO, and not
  2671.         data.
  2672.         --------------------------------------------------------------------- */
  2673.      
  2674.     /*
  2675.      * Since we're a driver, there's no one to send it on to.
  2676.      * Just free the message.
  2677.      */
  2678. //    OTKernelPrintf( kOTPrintThenStop, "proxy_data entered unexpectedly.\n");
  2679.     freemsg(mp);
  2680.     return ENXIO;
  2681. }
  2682.  
  2683. int proxy_wproto(queue_t* q, mblk_t* mp)
  2684. {
  2685.     proxy_struct*    myData = (proxy_struct*)q->q_ptr;
  2686.     //struct module_info* nextinfo;
  2687.     /*
  2688.      * If the message block is not big enough - blow it away
  2689.      */
  2690.     if ( mp->b_wptr - mp->b_rptr < sizeof(long) )
  2691.     {
  2692.         freemsg(mp);
  2693.         return 0;
  2694.     }
  2695.     /*
  2696.      * Look at the incoming primitive message
  2697.      */
  2698. //if ( ((union T_primitives*)mp->b_rptr)->type != T_INFO_REQ) {
  2699. //    OTKernelPrintf( kOTPrintOnly, "Entering proxy_wproto, prim_type: %d.\n",
  2700. //                ((union T_primitives*)mp->b_rptr)->type);
  2701. //}
  2702.  
  2703.     switch ( ((union T_primitives*)mp->b_rptr)->type )
  2704.     {
  2705.         /*
  2706.          * For incoming data, let proxy_wdata handle it
  2707.          */
  2708.         case T_UNITDATA_REQ:
  2709.             return proxy_wdata(q, mp);
  2710.  
  2711.         case T_INFO_REQ:
  2712.             //OTKernelPrintf( kOTPrintThenStop, "T_INFO_REQ \n");
  2713.             // respond with T_INFO_ACK
  2714.             mp = ReuseMessage(mp, sizeof(T_info_ack) );    // get a message block
  2715.             if (mp == nilp(mblk_t)) return ENOBUFS;
  2716.             mp->b_datap->db_type = M_PCPROTO;    // set message type
  2717.             ((T_info_ack*)mp->b_wptr)->PRIM_type    = T_INFO_ACK;
  2718.             ((T_info_ack*)mp->b_wptr)->TSDU_size    = 255;
  2719.             ((T_info_ack*)mp->b_wptr)->ETSDU_size    = -2;    // -2 for connectionless service
  2720.             ((T_info_ack*)mp->b_wptr)->CDATA_size    = -2;
  2721.             ((T_info_ack*)mp->b_wptr)->DDATA_size    = -2;
  2722.             ((T_info_ack*)mp->b_wptr)->ADDR_size    = sizeof(InetAddress);
  2723.             ((T_info_ack*)mp->b_wptr)->OPT_size        = -3;    // no options
  2724.             ((T_info_ack*)mp->b_wptr)->TIDU_size    = 255;
  2725.             ((T_info_ack*)mp->b_wptr)->SERV_type    = T_CLTS;
  2726.             ((T_info_ack*)mp->b_wptr)->CURRENT_state= myData->myState;
  2727.             ((T_info_ack*)mp->b_wptr)->PROVIDER_flag= SENDZERO;
  2728.             mp->b_wptr += sizeof(T_info_ack);
  2729.             qreply(q, mp);
  2730.             return 0;
  2731.  
  2732.         case T_OPTMGMT_REQ:
  2733.             //OTKernelPrintf( kOTPrintOnly, "T_OPTMGMT_REQ \n");
  2734.             // respond with T_OPTMGMT_ACK
  2735.             mp = ReuseMessage(mp, sizeof(T_optmgmt_ack) );    // get a message block
  2736.             if (mp == nilp(mblk_t)) return ENOBUFS;
  2737.             mp->b_datap->db_type = M_PCPROTO;    // set message type
  2738.             ((T_optmgmt_ack*)mp->b_wptr)->PRIM_type    = T_OPTMGMT_ACK;
  2739.             // others same as received
  2740.             mp->b_wptr += sizeof(T_optmgmt_ack);
  2741.             qreply(q, mp);
  2742.             return 0;
  2743.  
  2744.         case T_BIND_REQ:
  2745.             // respond with T_BIND_ACK
  2746.             // re-use message block
  2747.             mp->b_datap->db_type = M_PCPROTO;    // set message type
  2748.             ((T_bind_ack*)mp->b_rptr)->PRIM_type    = T_BIND_ACK;
  2749.             myData->myState = TS_IDLE;
  2750.             qreply(q, mp);
  2751.             return 0;
  2752.             
  2753.         case T_UNBIND_REQ:
  2754.             // respond with T_OK_ACK
  2755.             mp = ReuseMessage(mp, sizeof(T_ok_ack) );    // get a message block
  2756.             if (mp == nilp(mblk_t)) return ENOBUFS;
  2757.             mp->b_datap->db_type = M_PCPROTO;    // set message type
  2758.             ((T_ok_ack*)mp->b_wptr)->PRIM_type        = T_OK_ACK;
  2759.             ((T_ok_ack*)mp->b_wptr)->CORRECT_prim    = T_UNBIND_REQ;
  2760.             mp->b_wptr += sizeof(T_ok_ack);
  2761.             myData->myState = TS_UNBND;
  2762.             qreply(q, mp);
  2763.             return 0;
  2764.  
  2765.         default:
  2766.             break;
  2767.     }
  2768.     /*
  2769.      * Since we're a driver, there's no one to pass it on to.
  2770.      * Just free the message
  2771.      */
  2772. //    OTKernelPrintf( kOTPrintThenStop, "proxy_wproto, Unknown prim_type: %d.\n",
  2773. //                ((union T_primitives*)mp->b_rptr)->type);
  2774.     freemsg(mp);
  2775.     return ENXIO;
  2776. }
  2777.  
  2778. int proxy_wsrv(queue_t* q)
  2779. {
  2780.     mblk_t*    mp;
  2781.     /*
  2782.      * Send on downstream anything that was scheduled for flow control!
  2783.      * Since we're a driver, nothing should be scheduled
  2784.      */
  2785. //    OTKernelPrintf( kOTPrintThenStop, "proxy_wsrv, Unexpected data.\n");
  2786.  
  2787.     while ( (mp = getq(q)) != nilp(mblk_t) )
  2788.     {
  2789.         /*
  2790.          * If we're flow controlled, get out and we'll come back when the flow-
  2791.          * control lifts.
  2792.          */
  2793.         if ( !bcanput(q->q_next, mp->b_band) )
  2794.         {
  2795.             putbq(q, mp);
  2796.             return 0;
  2797.         }
  2798.         /*
  2799.          * Otherwise, send the data downstream, and get some more
  2800.          */
  2801.         //OTKernelPrintf( kOTPrintThenStop, "wsrv, putnext \n");
  2802.         putnext(q, mp);
  2803.     }
  2804.     return 0;
  2805. }
  2806.  
  2807. /*******************************************************************************
  2808. ** Read-side process routines
  2809. ********************************************************************************/
  2810.  
  2811. int proxy_rdata(queue_t* q, mblk_t* mp)
  2812. {
  2813.     proxy_struct* myData = (proxy_struct*)q->q_ptr;
  2814.     /*
  2815.      * If we're not ready for incoming data, just free it up
  2816.      */
  2817.     if ( myData->myState != DL_IDLE )
  2818.     {
  2819.         freemsg(mp);
  2820.         return 0;
  2821.     }
  2822.     
  2823.     /*    ---------------------------------------------------------------------
  2824.         Here, we do whatever munging we're going to do on the incoming data,
  2825.         then send it on.
  2826.         Keep in mind that we call this routine from the proxy_rproto routine,
  2827.         so that the first block of the message might be an M_PROTO, and not
  2828.         data.
  2829.         --------------------------------------------------------------------- */
  2830.      
  2831.      /*
  2832.       * Now, we send it on.  If we can't because of flow control, use
  2833.       * putq to put it on our queue and send it on later.
  2834.       */
  2835.      if ( !bcanput(q->q_next, mp->b_band) )
  2836.          putq(q, mp);
  2837.     else
  2838.         putnext(q, mp);
  2839.     return 0;
  2840. }
  2841.  
  2842. int proxy_rproto(queue_t* q, mblk_t* mp)
  2843. {
  2844.     Boolean            doOutState = false;
  2845.     proxy_struct*    myData = (proxy_struct*)q->q_ptr;
  2846.     /*
  2847.      * If the message block is not big enough - blow it away
  2848.      */
  2849.     if ( mp->b_wptr - mp->b_rptr < sizeof(long) )
  2850.     {
  2851.         freemsg(mp);
  2852.         return 0;
  2853.     }
  2854.     /*
  2855.      * Look at the incoming primitive message
  2856.      */
  2857.     switch ( ((union T_primitives*)mp->b_rptr)->type )
  2858.     {
  2859.         /*
  2860.          * For incoming data, let proxy_rdata handle it
  2861.          */
  2862.         case DL_UNITDATA_IND:
  2863.             return proxy_rdata(q, mp);
  2864.         /*
  2865.          * These are just passed on, since we don't deal with them
  2866.          */
  2867.         case DL_INFO_ACK:
  2868.         //case T_ADDR_ACK:
  2869.         //case T_RESOLVEADDR_ACK:
  2870.         //case T_OPTMGMT_ACK:
  2871.             break;
  2872.                     
  2873.         /*
  2874.          * Here, a bind request succeeded.
  2875.          */
  2876.         case DL_BIND_ACK:
  2877.             myData->myState = DL_IDLE;
  2878.             break;
  2879.             
  2880.         /*
  2881.          * Handle any error acks that come back
  2882.          */
  2883.         case DL_ERROR_ACK:
  2884.         {
  2885.             switch ( ((dl_error_ack_t*)mp->b_rptr)->dl_error_primitive )
  2886.             {
  2887.                 /*
  2888.                  * These are error acks for functions we just pass thru
  2889.                  */
  2890.                 case DL_INFO_REQ:
  2891.                 //case T_ADDR_REQ:
  2892.                 //case T_OPTMGMT_REQ:
  2893.                     break;
  2894.                 
  2895.                 /*
  2896.                  * If the unbind failed, then we are not unbound either.
  2897.                  * Send the error on up to the client.
  2898.                  */
  2899.                 case DL_UNBIND_REQ:
  2900.                     myData->myState = DL_IDLE;
  2901.                     break;
  2902.                     
  2903.                 /*
  2904.                  * If the bind failed, we fall back to the unbound state
  2905.                  */
  2906.                 case DL_BIND_REQ:
  2907.                     myData->myState = DL_UNBOUND;
  2908.                     break;
  2909.                     
  2910.                 //case T_CONN_REQ:
  2911.                 //case T_CONN_RES:
  2912.                 //case T_DISCON_REQ:
  2913.                 /*
  2914.                  * %%% Needs implementation
  2915.                  */
  2916.                  //break;
  2917.                  
  2918.                 /*
  2919.                  * Any error acks we don't understand just pass on
  2920.                  */
  2921.                 default:
  2922.                     break;
  2923.             }
  2924.             break;
  2925.         }
  2926.         
  2927.         /*
  2928.          * Handle any OK acks that come back
  2929.          */
  2930.         case DL_OK_ACK:
  2931.         {
  2932.             switch ( ((dl_ok_ack_t*)mp->b_rptr)->dl_correct_primitive )
  2933.             {
  2934.                 /*
  2935.                  * If the unbind is OK, we are no longer unbound.
  2936.                  */
  2937.                 case DL_UNBIND_REQ:
  2938.                     myData->myState = DL_UNBOUND;
  2939.                     break;
  2940.  
  2941.                 case DL_BIND_REQ:
  2942.                     myData->myState = DL_IDLE;
  2943.                     break;
  2944.                                         
  2945.                 //case T_CONN_REQ:
  2946.                 //case T_CONN_RES:
  2947.                 //case T_DISCON_REQ:
  2948.                 /*
  2949.                  * %%% Needs implementation - Kill any that have their
  2950.                  *     own acking mechanism.
  2951.                  */
  2952.                 // break;
  2953.                  
  2954.                 /*
  2955.                  * Any error acks we don't understand just pass on
  2956.                  */
  2957.                 default:
  2958.                     break;
  2959.             }
  2960.             break;
  2961.         }
  2962.         
  2963.         //case T_CONN_IND:
  2964.         //case T_CONN_CON:
  2965.         //case T_DISCON_IND:
  2966.         //case T_ORDREL_IND:
  2967.         /*
  2968.          * %%% Needs implementation
  2969.          */
  2970.         // break;
  2971.                     
  2972.         /*
  2973.          * Anything else we don't understand, just send it on
  2974.          */
  2975.         default:
  2976.             break;
  2977.     }    /*
  2978.      * Here, we just pass the message block on to the next layer, or
  2979.      * queue it up till flow control is lifted.
  2980.      */
  2981.     if (mp->b_datap->db_type > QPCTL || canput(q->q_next) )
  2982.         putnext(q, mp);
  2983.     else
  2984.         putq(q, mp);
  2985.     return 0;
  2986. }
  2987.  
  2988. int proxy_rsrv(queue_t* q)
  2989. {
  2990.     mblk_t*    mp;
  2991.     /*
  2992.      * Send on up anything that was scheduled for flow control!
  2993.      */
  2994.     while ( (mp = getq(q)) != nilp(mblk_t) )
  2995.     {
  2996.         /*
  2997.          * If we're flow controlled, get out and we'll come back when the flow-
  2998.          * control lifts.
  2999.          */
  3000.         if ( !bcanput(q->q_next, mp->b_band) )
  3001.         {
  3002.             putbq(q, mp);
  3003.             return 0;
  3004.         }
  3005.         /*
  3006.          * Otherwise, send the data upstream, and get some more
  3007.          */
  3008.         putnext(q, mp);
  3009.     }
  3010.     return 0;
  3011. }
  3012.  
  3013. #pragma mark • generic support functions •
  3014.  
  3015. // ---------------------------------------------------------------------------------
  3016. //    • proxy Get Timed Stat
  3017. // ---------------------------------------------------------------------------------
  3018. //    Return timed stat data counters and reset
  3019. void proxy_GetTimedStat(queue_t* q, SInt32* outSequenceNumber, SInt32* outRCount, SInt32* outWCount)
  3020. {
  3021.     proxy_struct*    myData = (proxy_struct*)q->q_ptr;
  3022.     
  3023.     SInt32 myRCount;
  3024.     SInt32 myWCount;
  3025.  
  3026.     // read the stat values
  3027.     myRCount = mstat.rCount;
  3028.     myWCount = mstat.wCount;
  3029.     
  3030.     // Reset the data counters carefully so we don't miss anything
  3031.     // (subtract only the number we read)
  3032.     OTAtomicAdd32(-myRCount, &mstat.rCount);
  3033.     OTAtomicAdd32(-myWCount, &mstat.wCount);
  3034.  
  3035.     // set return values (if pointers are not nil)
  3036.     if (outSequenceNumber)    *outSequenceNumber    = myData->timerSequenceNumber;
  3037.     if (outRCount)             *outRCount             = myRCount;
  3038.     if (outWCount)             *outWCount             = myWCount;
  3039.  
  3040.     myData->timerUnAckCount += 1;            // Increment Unacked so we can stop if needed.
  3041.     myData->timerSequenceNumber += 1;        // increment timer sequence number for reference
  3042. }
  3043.  
  3044.  
  3045. // ---------------------------------------------------------------------------------
  3046. //    • proxy Send Filters
  3047. // ---------------------------------------------------------------------------------
  3048. //    Sends Filter table to client
  3049. Boolean proxy_SendFilters(queue_t* q)
  3050. {
  3051.     mblk_t*             fmp;    // filter message pointer
  3052.     mblk_t*             udmp;    // unit data message pointer
  3053.     InetAddress         src;
  3054.     UInt32                opt;
  3055.     dl_filter_message_t* mb;    // message buffer
  3056.     size_t                size;
  3057.     //proxy_struct*        myData = (proxy_struct*)q->q_ptr;
  3058.  
  3059.     FilterTableData_t*    data;        // Filter table access
  3060.     UInt16                index;
  3061.     UInt16                loopCount;    // defensive prevent looping
  3062.     UInt8                count;
  3063.     Boolean                result = false;
  3064.         
  3065.     // get Filter table threads
  3066.     data = (FilterTableData_t*)gFilterTable;
  3067.     // walk active entry list
  3068.     index = data->firstActive;
  3069.     loopCount = 0;
  3070.     
  3071.     do {    
  3072.         // create an M_DATA message to send our Filter data
  3073.         size = sizeof(dl_filter_message_t);
  3074.         fmp = allocb(size, BPRI_LO);
  3075.         if (fmp == nilp(mblk_t)) {        // if we didn't get a block
  3076.             break;                // get out
  3077.         }
  3078.         // Standard defines type = M_DATA, b_rptr and b_wptr to b_datap->db_base,
  3079.         // b_band = 0, ref count = 1
  3080.         
  3081.         // set data in message buffer
  3082.         mb = (dl_filter_message_t*)fmp->b_wptr;
  3083.         mb->dl_primitive    = DL_FILTER_MESSAGE;
  3084.         // transfer table data to buffer    
  3085.         count = 0;
  3086.         while ((index > 0) && (count < kFilterMessageDim)) {
  3087.             mb->array[count].portName    = gFilterTable[index].portName;
  3088.             mb->array[count].flags        = gFilterTable[index].flags;
  3089.             mb->array[count].protocol    = gFilterTable[index].protocol;
  3090.             mb->array[count].sourceNet.address    = gFilterTable[index].sourceNet.address;
  3091.             mb->array[count].sourceNet.mask        = gFilterTable[index].sourceNet.mask;
  3092.             mb->array[count].sourcePorts.lo        = gFilterTable[index].sourcePorts.lo;
  3093.             mb->array[count].sourcePorts.hi        = gFilterTable[index].sourcePorts.hi;
  3094.             mb->array[count].destNet.address    = gFilterTable[index].destNet.address;
  3095.             mb->array[count].destNet.mask        = gFilterTable[index].destNet.mask;
  3096.             mb->array[count].destPorts.lo        = gFilterTable[index].destPorts.lo;
  3097.             mb->array[count].destPorts.hi        = gFilterTable[index].destPorts.hi;
  3098.             mb->array[count].entryID    = index;
  3099.             count += 1;
  3100.  
  3101.             index = gFilterTable[index].entryID;
  3102.             loopCount += 1;        // defensive, test for bad link
  3103.             if ((index > data->lastUsed) || (loopCount > data->lastUsed)) break;
  3104.         }
  3105.         if (index) mb->dl_status = 1;    // more entries?
  3106.         else mb->dl_status    = 0;
  3107.         mb->dl_number        = count;    // number of entries included
  3108.  
  3109.         // initialize the message
  3110.         fmp->b_cont = nilp(mblk_t);                // no trailer
  3111.         fmp->b_wptr = fmp->b_rptr + size;
  3112.         
  3113.         // Create a T_UNITDATA_IND message with our stat message block attached
  3114.         //OTInitInetAddress(&src, (InetPort)0, (InetHost)0);
  3115.         BZERO(&src, sizeof(InetAddress));
  3116.         src.fAddressType = AF_INET;
  3117.         src.fPort = 0;
  3118.         src.fHost = DL_FILTER_MESSAGE;
  3119.         opt = 0;
  3120.         udmp = my_tpi_unitdata_ind(fmp, (char*)&src, sizeof(InetAddress), (char*)&opt, 0);
  3121.         if (udmp == nilp(mblk_t)) {
  3122.             freemsg(fmp);                // release the M_DATA message
  3123.             break;                // get out
  3124.         }
  3125.  
  3126.         // schedule ourselves to send T_UNITDATA_IND messages upstream.
  3127.          putq(q, udmp);
  3128.          result = true;
  3129.  
  3130.         // defensive, test for bad link
  3131.         if ((index > data->lastUsed) || (loopCount > data->lastUsed)) break;
  3132.  
  3133.     } while (index != 0);
  3134.     
  3135.     return result;
  3136. }
  3137.  
  3138.  
  3139. // ---------------------------------------------------------------------------------
  3140. //    • proxy Send Nat
  3141. // ---------------------------------------------------------------------------------
  3142. //    Sends NAT table to client
  3143. Boolean proxy_SendNat(translationEntry_t table[], queue_t* q, UInt8 selector)
  3144. {
  3145.     mblk_t*             nmp;    // NAT message pointer
  3146.     mblk_t*             udmp;    // unit data message pointer
  3147.     InetAddress         src;
  3148.     UInt32                opt;
  3149.     dl_port_map_t*        mb;        // message buffer
  3150.     size_t                size;
  3151.     //proxy_struct*        myData = (proxy_struct*)q->q_ptr;
  3152.  
  3153.     tableData_t*        data;        // NAT table access
  3154.     UInt16                index;
  3155.     UInt16                loopCount;    // defensive prevent looping
  3156.     UInt8                count;
  3157.     Boolean                result = false;
  3158.         
  3159.     // get NAT table threads
  3160.     data = (tableData_t*)table;
  3161.     // walk active entry list
  3162.     index = data->firstActive;
  3163.     loopCount = 0;
  3164.     
  3165.     do {    
  3166.         // create an M_DATA message to send our NAT data
  3167.         size = sizeof(dl_port_map_t);
  3168.         nmp = allocb(size, BPRI_LO);
  3169.         if (nmp == nilp(mblk_t)) {        // if we didn't get a block
  3170.             break;                // get out
  3171.         }
  3172.         // Standard defines type = M_DATA, b_rptr and b_wptr to b_datap->db_base,
  3173.         // b_band = 0, ref count = 1
  3174.         
  3175.         // set data in message buffer
  3176.         mb = (dl_port_map_t*)nmp->b_wptr;
  3177.         mb->dl_primitive    = DL_PORT_MAP;
  3178.         // transfer table data to buffer    
  3179.         count = 0;
  3180.         while ((index > 0) && (count < kPortMapEntryDim)) {
  3181.             if ((selector == kFullMap) ||
  3182.                 ((selector == kStaticMap) && (table[index].flags & kFlagPermanent))) {            
  3183.                 mb->array[count].apparent    = table[index].apparent;
  3184.                 mb->array[count].portRange    = table[index].portRange;
  3185.                 mb->array[count].actual        = table[index].actual;
  3186.                 mb->array[count].age        = table[index].age;
  3187.                 mb->array[count].flags        = table[index].flags;
  3188.                 mb->array[count].protocol    = table[index].protocol;
  3189.                 count += 1;
  3190.             }
  3191.             index = table[index].entryID;
  3192.             loopCount += 1;        // defensive, test for bad link
  3193.             if ((index > data->lastUsed) || (loopCount > data->lastUsed)) break;
  3194.         }
  3195.         if (index) mb->dl_status = 1;    // more entries?
  3196.         else mb->dl_status    = 0;
  3197.         mb->dl_number        = count;    // number of entries included
  3198.  
  3199.         // initialize the message
  3200.         nmp->b_cont = nilp(mblk_t);                // no trailer
  3201.         nmp->b_wptr = nmp->b_rptr + size;
  3202.         
  3203.         // Create a T_UNITDATA_IND message with our stat message block attached
  3204.         //OTInitInetAddress(&src, (InetPort)0, (InetHost)0);
  3205.         BZERO(&src, sizeof(InetAddress));
  3206.         src.fAddressType = AF_INET;
  3207.         src.fPort = 0;
  3208.         src.fHost = DL_PORT_MAP;
  3209.         opt = 0;
  3210.         udmp = my_tpi_unitdata_ind(nmp, (char*)&src, sizeof(InetAddress), (char*)&opt, 0);
  3211.         if (udmp == nilp(mblk_t)) {
  3212.             freemsg(nmp);                // release the M_DATA message
  3213.             break;                // get out
  3214.         }
  3215.  
  3216.         // schedule ourselves to send T_UNITDATA_IND messages upstream.
  3217.          putq(q, udmp);
  3218.          result = true;
  3219.  
  3220.         // defensive, test for bad link
  3221.         if ((index > data->lastUsed) || (loopCount > data->lastUsed)) break;
  3222.  
  3223.     } while (index != 0);
  3224.     
  3225.     return result;
  3226. }
  3227.  
  3228.  
  3229. // ---------------------------------------------------------------------------------
  3230. //    • proxy Send Stats
  3231. // ---------------------------------------------------------------------------------
  3232. //    Send stats to client - returns true if stats were sent
  3233. Boolean proxy_SendStats(queue_t* q)
  3234. {
  3235.     mblk_t*             smp;    // stat message pointer
  3236.     mblk_t*             udmp;    // unit data message pointer
  3237.     InetAddress         src;
  3238.     UInt32                opt;
  3239.     dl_timed_stat_t*    sb;        // stat buffer
  3240.     size_t                size;
  3241.     proxy_struct*        myData = (proxy_struct*)q->q_ptr;
  3242.     
  3243.     // If client isn't updating, stop sending
  3244.     if (myData->timerUnAckCount > 31) {    // limit 30 unacked
  3245.         proxy_GetTimedStat(q, nil, nil, nil);    // re-initialize stat counters
  3246.         return false;
  3247.     }
  3248.     
  3249.     // create an M_DATA message to send our timed stat data
  3250.     size = sizeof(dl_timed_stat_t);
  3251.     smp = allocb(size, BPRI_LO);
  3252.     if (smp == nilp(mblk_t)) {        // if we didn't get a block
  3253.         return false;                // get out
  3254.     }
  3255.     // Standard defines type = M_DATA, b_rptr and b_wptr to b_datap->db_base,
  3256.     // b_band = 0, ref count = 1
  3257.     
  3258.     // set data in message buffer
  3259.     sb = (dl_timed_stat_t*)smp->b_wptr;
  3260.     sb->dl_primitive    = DL_TIMED_STAT;
  3261.     proxy_GetTimedStat(q, &sb->dl_sequence, &sb->dl_rCount, &sb->dl_wCount);
  3262.  
  3263.     // initialize the message
  3264.     smp->b_cont = nilp(mblk_t);                // no trailer
  3265.     smp->b_wptr = smp->b_rptr + size;
  3266.     
  3267.     // Create a T_UNITDATA_IND message with our stat message block attached
  3268.     //OTInitInetAddress(&src, (InetPort)0, (InetHost)0);
  3269.     BZERO(&src, sizeof(InetAddress));
  3270.     src.fAddressType = AF_INET;
  3271.     src.fPort = 0;
  3272.     src.fHost = DL_TIMED_STAT;
  3273.     opt = 0;
  3274.     udmp = my_tpi_unitdata_ind(smp, (char*)&src, sizeof(InetAddress), (char*)&opt, 0);
  3275.     if (udmp == nilp(mblk_t)) {
  3276.         freemsg(smp);                // release the M_DATA message
  3277.         return false;                // get out
  3278.     }
  3279.  
  3280.     // send T_UNITDATA_IND message upstream.
  3281.     if ( !bcanput(q->q_next, udmp->b_band) ) {
  3282.          putq(q, udmp);
  3283.     } else {
  3284.         putnext(q, udmp);
  3285.     }
  3286.     return true;
  3287. }
  3288.  
  3289.  
  3290. // ---------------------------------------------------------------------------------
  3291. //    • mi_tpi_unitdata_ind
  3292. // ---------------------------------------------------------------------------------
  3293. //    Allocate and initialize a unitdata indication message
  3294. mblk_t*    my_tpi_unitdata_ind(mblk_t* trailer_mp, char* src, size_t src_length,
  3295.     char* opt, size_t opt_length)
  3296. {
  3297.     mblk_t*    mp;
  3298.     size_t    size;
  3299.     T_unitdata_ind* ud;
  3300.     
  3301.     // create a T_UNITDATA_IND message
  3302.     size = sizeof(T_unitdata_ind) + src_length + opt_length;
  3303.     mp = allocb(size, BPRI_LO);
  3304.     if (mp == nilp(mblk_t)) {            // if we didn't get a block
  3305.         return nilp(mblk_t);            // get out
  3306.     }
  3307.     // Standard defines type = M_DATA, b_rptr and b_wptr to b_datap->db_base,
  3308.     // b_band = 0, ref count = 1
  3309.  
  3310.     // initialize message in data buffer
  3311.     ud = (T_unitdata_ind*)mp->b_wptr;
  3312.     ud->PRIM_type = T_UNITDATA_IND;
  3313.     ud->SRC_length = src_length;
  3314.     ud->SRC_offset = sizeof(T_unitdata_ind);    
  3315.     ud->OPT_length = opt_length;
  3316.     ud->OPT_offset = ud->SRC_offset + src_length;
  3317.     mp->b_wptr += sizeof(T_unitdata_ind);
  3318.     if (src_length > 0)
  3319.         bcopy(src, mp->b_wptr, src_length);
  3320.     mp->b_wptr += src_length;
  3321.     if (opt_length > 0)
  3322.         bcopy(opt, mp->b_wptr, opt_length );
  3323.     mp->b_wptr += opt_length;
  3324.     
  3325.     // initialize the message
  3326.     mp->b_cont = trailer_mp;            // attach trailer mp
  3327.     mp->b_datap->db_type = M_PROTO;        // set message type
  3328.     
  3329.     return mp;
  3330. }
  3331.  
  3332.  
  3333.  
  3334. #pragma mark • Macintosh Install Info •
  3335.  
  3336. /* ------------------------------------------------------------------------
  3337.  
  3338.     THESE FUNCTIONS AND DATA STRUCTURES ARE SPECIFIC TO THE MACINTOSH IMPLEMENTATION
  3339.     OF STREAMS. THESE ROUTINES WOULD NOT EXIST IN OTHER STREAMS ENVIRONMENTS.
  3340.     
  3341.     WHEN PORTING OTHER STREAMS CODE TO THE MACINTOSH, THESE ROUTINES AND DATA
  3342.     STRUCTURES MUST BE ADDED.
  3343.  
  3344.   ------------------------------------------------------------------------ */
  3345. install_info* GetOTProxyInstallInfo();
  3346. Boolean    InitProxyStreamModule(void* cookie);
  3347.  
  3348. /*******************************************************************************
  3349. ** install_info structure, and the GetInstallInfo function
  3350. **
  3351. ** This is the structure that tells Open Transport about your module. OT calls
  3352. ** your "GetInstallInfo" function to get this information.
  3353. **
  3354. ********************************************************************************/
  3355.     
  3356. install_info* GetOTProxyInstallInfo()
  3357. {
  3358.     return &proxyInstallInfo;
  3359. }
  3360.  
  3361. /*******************************************************************************
  3362. ** This is the function that will be called the first time that this code
  3363. ** is loaded.  It is guaranteed that this function is call at SystemTask time
  3364. ** on the Macintosh.
  3365. ********************************************************************************/
  3366.  
  3367. Boolean InitProxyStreamModule(void* cookie)
  3368. {
  3369. //    UInt8    i;
  3370.     
  3371.     /* Do any machine specific initialization stuff you need to */;
  3372.     gProxyListHead = NULL;
  3373.     proxyRefCountAdjusted    = false;
  3374.     // Init the NAT table
  3375.     gNatTable[0] = gNatTable0;
  3376.     gNatTable[1] = gNatTable1;
  3377.     gNatTable[2] = gNatTable2;
  3378.     gNatTable[3] = gNatTable3;
  3379. //    for (i=0; i<kNatNumDim; i++) {
  3380. //        InitTable(gNatTable[i]);
  3381. //    }
  3382.     gIsLocalNatOn = false;
  3383.     gIsTRCableModem = false;
  3384.     gIsDNSForwarding = true;            // DNS forwarding defaults to On
  3385.     gIsOnDemandUp = true;
  3386.     gIsOnDemandPending = false;
  3387.     gOnDemandName = HashName("IPCP");    // invoke IPCP driver On Demand
  3388.     gOnDemandSrcAddress = 0;
  3389.     gMonitorName = 0;
  3390.     // Init the Filter table
  3391. //    InitFilterTable(gFilterTable);
  3392.     
  3393.     // Init FlakeWay
  3394.     gFlakePercent = 0;
  3395.     gFlakeLatency = 0;
  3396.     
  3397.     return true;
  3398. }
  3399.